I am using adal.js 1.0.14, below is my login
var authenticationContext = new AuthenticationContext(config);
if (!config.popUp) {
if (authenticationContext.isCallback(window.location.hash)) {
authenticationContext.handleWindowCallback();
}
}
var user = authenticationContext.getCachedUser();
sessionStorage.setItem("adal:Tenant","#CommonMethods.GetAppConfigValue("ida:TenantId")")
if (!user) {
authenticationContext.login();
}
below is my renewal code
this.authenticationContext.getCachedUser();
this.authenticationContext.acquireToken(config.clientId, function (errorDesc, token) {
if (errorDesc) {
console.log("ErrorDesc", errorDesc);
}
if (token) {
console.log("calling the Web API with the access token", token);
}
});
but i got "User login is required". Can't understand what happen with this.
I got the problem, the problem is, I use below config settings for authentication
var config = {
tenant: window.sessionStorage.getItem('adal:Tenant'),
clientId: window.sessionStorage.getItem('adal.token.keys'),
redirectUri: baseURL,
popUp: false,
postLogoutRedirectUri: baseURL,
expireOffsetSeconds: 3540
}
in above code, the ClientId contain '|', because of which can't get token and user information. I update my config settings,
var config = {
tenant: window.sessionStorage.getItem('adal:Tenant'),
clientId: window.sessionStorage.getItem('adal.token.keys').replace('|', ''),
redirectUri: baseURL,
popUp: false,
postLogoutRedirectUri: baseURL,
expireOffsetSeconds: 3540
}
And it works.
Related
I am using Okta Sign In widget for authentication but even after successful login there is no redirection instead it keeps loading for unlimited time
these are my configs:
oidc: {
url: 'https://{yourOktaDomain}',
issuer: 'https://{yourOktaDomain}/oauth2/default',
redirectUri: `${window.location.origin}/implicit/callback`,
clientId: `{clientId}`,
scopes: ['openid', 'profile', 'email'],
pkce: true
},
postLogoutRedirectUri: `${window.location.origin}/login`
and these are widget initialization:
const { issuer, clientId, redirectUri, scopes, url } = config.oidc;
const widget = new OktaSignIn({
baseUrl: url,
clientId,
redirectUri,
logo: '/react.svg',
i18n: {
en: {
'primaryauth.title': 'Sign in using Okta',
},
},
authParams: {
issuer,
scopes,
},
});
I have already added trusted origin in Okta Console:
Trusted origins image
Also, already added Redirection URIs in Okta Application:
Redirection URIs image
I am getting user undefined in following code.
I have already authenticated user from MVC.
But when I use signinSilentCallback to get detail of that user, it is getting undefined using oidc-client in js.
It doesn't give any error as well.
var mgr = new UserManager({
authority: "http://localhost:5000",
client_id: "js",
redirect_uri: "http://localhost:50144/signin-oidc",
silent_redirect_uri: "http://localhost:50144/signin-oidc",
response_type: "id_token token",
post_logout_redirect_uri: "http://localhost:50144/signout-callback-oidc",
});
mgr.signinSilentCallback().then(function (user) {
//**Here user is undefined.**
axios.defaults.headers.common['Authorization'] = "Bearer " + user.access_token;
});
In Identityserver 4, client is defined as following.
new Client
{
ClientId = "js",
ClientName = "js",
ClientUri = "http://localhost:50144",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RequireClientSecret = false,
AccessTokenType = AccessTokenType.Jwt,
RedirectUris =
{
"http://localhost:50144/signin-oidc",
},
PostLogoutRedirectUris = { "http://localhost:50144/signout-callback-oidc" },
AllowedCorsOrigins = { "http://localhost:50144" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email
}
}
signinSilentCallback: Returns promise to notify the parent window of response from the authorization endpoint.
https://github.com/IdentityModel/oidc-client-js/wiki
signinSilentCallback - This is not something will return you the user object.
If you really need to get the user object on silent renew i would suggest to use this approach with folloowing code snippet. This works for me in salesforce apps as well.
this.userManager.events.addAccessTokenExpiring(() =>
{
this.userManager.signinSilent({scope: oidcSettings.scope, response_type: oidcSettings.response_type})
.then((user: CoreApi.Authentication.Interfaces.OidcClientUser) =>
{
this.handleUser(user); // This function just set the current user
})
.catch((error: Error) =>
{
this.userManager.getUser()
.then((user: CoreApi.Authentication.Interfaces.OidcClientUser) =>
{
this.handleUser(user);
});
});
});
We need to handle the getUser in catch as well due to one of bug reported for iFrame in oidc-client js
From above code focus on the way the silent renew is performed when the token expires.
you can set automaticSilentRenew to true in your config
var mgr = new UserManager({
authority: "http://localhost:5000",
client_id: "js",
redirect_uri: "http://localhost:50144/signin-oidc",
silent_redirect_uri: "http://localhost:50144/signin-oidc",
response_type: "id_token token",
post_logout_redirect_uri: "http://localhost:50144/signout-callback-oidc",
automaticSilentRenew: true; //here
});
and you can use UserManager events to load the new user when the token is refreshed
this.mgr.events.addUserLoaded(args => {
this.mgr.getUser().then(user => {
this._user = user; // load the new user
});
});
I am using passport facebook for user authentication in my web app. My Node backed is running on localhost:8080 and angular frontend is running on localhost:4200. How can I save the data received from Facebook, Save it to a database and then pass that database data to my angular frontend? I tried so many guides and tutorials online, all of those are running on the same domain, but mine is different domains(8080 & 4200).
Below is my social auth code, if it can be of any help.
module.exports = function(app, db) {
var express = require('express'),
ObjectID = require("mongodb").ObjectID,
passport = require('passport'),
FacebookStrategy = require('passport-facebook').Strategy,
GoogleStrategy = require( 'passport-google-oauth2' ).Strategy,
LinkedInStrategy = require('passport-linkedin');
var authConfig = require('../config/socialConfig');
var session = require('express-session');
app.use(passport.initialize());
app.use(passport.session());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}))
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new FacebookStrategy({
clientID: authConfig.facebookAuth.clientID,
clientSecret:authConfig.facebookAuth.clientSecret ,
callbackURL: authConfig.facebookAuth.callbackURL,
profileFields: ['id', 'displayName', 'photos', 'email']
},
function(token, refreshToken, profile, done) {
console.log("Hello" + profile);
// User.findOrCreate(..., function(err, user) {
// if (err) { return done(err); }
// done(null, user);
// });
done(null, profile);
}
));
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }));
app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' }));
}
And below is my frontend link to facebook auth
Facebook Login
Any help will be highly appreciated. Looking forward to some help, thanks in advance.
Since you Node.js app is on the other port, you need to specify the full URL to the /auth/facebook API (http://localhost:4020/auth/facebook).
Also, quoting the another post:
For two documents to be considered to have the same origin, the protocol >(http/https), the domain and the port (the default 80 or :xx) have to be >indentical
So you need to enable CORS on your node.js server. An easy way to do it is to use Express-cors npm
const cors = require('cors')
const app = express()
app.use(cors())
Hi I'm using Auth0 with Nodejs and angularjs
here is what i want to achieve
1. I want to user to signup using auth0's lock
2. as soon as user logs in a callback should be called at my nodejs server
3. after that i will get the user information and user's JWT
4. then i will redirect user to dashboard page and store the JWT in browser
What's the problem with Auth0's example
1. they provide example either for angular or nodejs standalone not the combined
2. there is combined(client server) example but that's using jade with nodejs
my code snipped
Angular snipped
var options = { auth: {
redirectUrl: 'http://localhost:3000/callback'
, responseType: 'code'
, params: {
scope: 'openid name email picture'
}
}
}
lockProvider.init({
clientID: 'cUlBNhhaIblahBlahRp6Km',
domain: 'rishabh.auth0.com',
option:options
});
node snipped
router.get('/callback',
passport.authenticate('auth0', { failureRedirect: '/url-if-something-fails' }),
function(req, res) {
console.log(req.user);
res.json({id_token:req.user});
});
Note: I've added this callbacks in auth0
http://localhost:3000/callback
but dont know why I'm facing this error for callback error when I've mentioned my redirect URL in angular side
can anyone tell me what is the problem with my code why auth0 not redirecting me to this url http://localhost:3000/callback
and the interesting thing is when i use simple lock.js instead of angular like this
<script>
var options = { auth: {
redirectUrl: 'http://localhost:3000/callback'
, responseType: 'code'
, params: {
scope: 'openid name email picture'
}
}
}
var lock = new Auth0Lock('clientID', 'rishabh.auth0.com',options);
lock.show();
</script>
then in this case my nodejs /callback route is called properly, so what I'm doing wrong with angular ?
please help
Update
this is my project structure
full code
https://github.com/LabN36/error
Config.js
var Auth0Strategy = require('passport-auth0');
var passport = require('passport');
var strategy = new Auth0Strategy({
domain: process.env.AUTH0_DOMAIN || 'rishabh.auth0.com',
clientID: process.env.AUTH0_CLIENT_ID || 'cUheWwRxm7OLdHBRzlBNvfvfvfvfvhhaI1lxRp6Km',
clientSecret: process.env.AUTH0_CLIENT_SECRET || 'e37eIZpjgBnDMBtrYMwvffvfvfvfaU4jSqt8qylZMT9Oj1EiffLGViinWQ5AiuWi1-WBwA8v3',
callbackURL: process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/callback'
}, function(accessToken, refreshToken, extraParams, profile, done) {
// accessToken is the token to call Auth0 API (not needed in the most cases)
// extraParams.id_token has the JSON Web Token
// profile has all the information from the user
console.log(extraParams.id_token);
//save user detail with token here and return token only profile
return done(null, extraParams.id_token);
});
passport.use(strategy);
// you can use this section to keep a smaller payload
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
module.exports = passport;
AngularApp.js
angular.module('workApp',['auth0.lock'])
.config(function($locationProvider,lockProvider){
var options = { auth: {
// redirect:true,
responseType: 'code',
redirectUrl: 'http://localhost:3000/callback',
params: {
scope: 'openid name email picture'
}
}
}
lockProvider.init({clientID: 'cUheWwRxm7OLdHBRzlBNhhaI1lxRp6Km',domain: 'rishabh.auth0.com',
option:options
});
$locationProvider.html5Mode(true);
})
.controller('homeCtrl',function($scope,$http,$location,$window,lock){
$scope.login = function() {
// window.alert("magic")
console.log("Messed Up really")
var vm = this;
vm.lock = lock;
lock.show();
}
}).run(function(lock){
lock.interceptHash();
lock.on('authenticated', function(authResult) {
localStorage.setItem('id_token', authResult.idToken);
lock.getProfile(authResult.idToken, function(error, profile) {
if (error) {
console.log(error);
}
localStorage.setItem('profile', JSON.stringify(profile));
});
});
})
According to the screenshot the error happens because the authentication request is made with a redirect_uri of:
http://localhost:3000/
and the allowed callback URL's are:
http://localhost:3000/callback
http://35.162.118.253:3000/callback
Also based on the code you shared you're indeed setting the redirectUrl to be http://localhost:3000/callback so there may be something on the rest of the code that either causes that value to be overridden or not used at all.
If the redirectUrl is not set, Lock will use the current page so the likely culprit is that the options you set are not being used. If you still don't find the cause for this, update the question with the code associated with how Lock is shown.
Damn, the actual root cause was already shown in the code you initially provided, but only looking now at the full code made it possible for me to catch it...
You're calling lockProvider.init() with:
{ clientID: [?], domain: [?], option: options }
when it should be called with:
{ clientID: [?], domain: [?], options: options } // options instead of option
This is an express route from angularjs satellizer example, implementing 3 legged OAuth with Twitter:
/*
|--------------------------------------------------------------------------
| Login with Twitter
|--------------------------------------------------------------------------
*/
app.get('/auth/twitter', function(req, res) {
var requestTokenUrl = 'https://api.twitter.com/oauth/request_token';
var accessTokenUrl = 'https://api.twitter.com/oauth/access_token';
var authenticateUrl = 'https://api.twitter.com/oauth/authenticate';
if (!req.query.oauth_token || !req.query.oauth_verifier) {
var requestTokenOauth = {
consumer_key: config.TWITTER_KEY,
consumer_secret: config.TWITTER_SECRET,
callback: config.TWITTER_CALLBACK
};
// Step 1. Obtain request token for the authorization popup.
request.post({ url: requestTokenUrl, oauth: requestTokenOauth }, function(err, response, body) {
var oauthToken = qs.parse(body);
var params = qs.stringify({ oauth_token: oauthToken.oauth_token });
// Step 2. Redirect to the authorization screen.
res.redirect(authenticateUrl + '?' + params);
});
} else {
var accessTokenOauth = {
consumer_key: config.TWITTER_KEY,
consumer_secret: config.TWITTER_SECRET,
token: req.query.oauth_token,
verifier: req.query.oauth_verifier
};
// Step 3. Exchange oauth token and oauth verifier for access token.
request.post({ url: accessTokenUrl, oauth: accessTokenOauth }, function(err, response, profile) {
profile = qs.parse(profile);
// Step 4a. Link user accounts.
if (req.headers.authorization) {
User.findOne({ twitter: profile.user_id }, function(err, existingUser) {
if (existingUser) {
return res.status(409).send({ message: 'There is already a Twitter account that belongs to you' });
}
var token = req.headers.authorization.split(' ')[1];
var payload = jwt.decode(token, config.TOKEN_SECRET);
User.findById(payload.sub, function(err, user) {
if (!user) {
return res.status(400).send({ message: 'User not found' });
}
user.twitter = profile.user_id;
user.displayName = user.displayName || profile.screen_name;
user.save(function(err) {
res.send({ token: createToken(user) });
});
});
});
} else {
// Step 4b. Create a new user account or return an existing one.
User.findOne({ twitter: profile.user_id }, function(err, existingUser) {
if (existingUser) {
var token = createToken(existingUser);
return res.send({ token: token });
}
var user = new User();
user.twitter = profile.user_id;
user.displayName = profile.screen_name;
user.save(function() {
var token = createToken(user);
res.send({ token: token });
});
});
}
});
}
});
The problem is Step 3:
var accessTokenOauth = {
consumer_key: config.TWITTER_KEY,
consumer_secret: config.TWITTER_SECRET,
token: req.query.oauth_token,
verifier: req.query.oauth_verifier
};
// Step 3. Exchange oauth token and oauth verifier for access token.
request.post({ url: accessTokenUrl, oauth: accessTokenOauth });
Because the node-request documentation describes Step 3 as:
// step 3
// after the user is redirected back to your server
var auth_data = qs.parse(body)
, oauth =
{ consumer_key: CONSUMER_KEY
, consumer_secret: CONSUMER_SECRET
, token: auth_data.oauth_token
, token_secret: req_data.oauth_token_secret
, verifier: auth_data.oauth_verifier
}
, url = 'https://api.twitter.com/oauth/access_token'
;
request.post({url:url, oauth:oauth}
The difference is, in the satellizer example, it doesn't pass token_secret to sign-in, but it should. So is this a mistake or what am I missing?
The real problem for me was, 3 legged twitter sign-in flow actually requires session on server side, but the satellizer example doesn't use any sessions, so I was wondering how this possible without sessions, but either it is not possible and satellizer example is wrong, or I don't understand something.