I am working on Node.js application with Cloudant database. I was able to do IBM IDP authentication with SSO server on Blue mix via the SSO service.
My issue occurs after successful authentication, I am unable to get JSON object that can give me all the user attributes that I need, for example, is the logged in person a manager? if yes then his serial number, name etc
Does anyone know how to retrieve the information from IBM SSO service?
Kindly let me know as soon as possible.
You can check the request.user object returned after successful authentication. It returns some information about the logged in user, but each provider returns different data.
For example, for LinkedIn logged users it returns displayName, firstName, lastName and emailAddress.
The snippet code below prints the request.user JSON object in the application log, so you can see what is available and retrieve as needed.
app.get('/auth/sso/callback', function(req, res, next) {
var redirect_url = req.session.originalUrl;
passport.authenticate('openidconnect', {
successRedirect: '/hello',
failureRedirect: '/failure',
})(req,res,next);
});
app.get('/hello', ensureAuthenticated, function(request, response) {
response.send('Hello, '+ request.user['id'] + '!\n' + 'Log Out');
console.log(JSON.stringify(request.user));
});
After user logs in you can run:
cf logs <app-name> --recent
to see results from console.log code.
Related
I have set up a Keycloak server and a user named 'sample' is given permissions to access the rest ADMIN APIs, I granted permissions to the relevant realm and client_id. And I'm able to access the rest APIs using the postman service using this user credentials 'sample/sample'.
so through Angular application, I was trying to access the API that fetches the roles in a specific realm. since not all the login user will have the rest admin access, I'm using the user credentials(sample/sample) that have the access to admin API, but when I try to access the API, the APIs are forbidden,
this.getKeycloakAccessToken().subscribe((Tokres:any)=>{
console.log('accessToken: ', Tokres.body.access_token);
if(Tokres && Tokres.status === 200 && Tokres.body.access_token){
this.getKeycloakRoles(Tokres.body.access_token).subscribe((roleRes:any)=>{
console.log(roleRes);
},(roleErr:any)=>{
console.log('error while fetching roles..');
console.log(roleErr);
})
}
},(tokErr:any)=>{
console.log('error while accessing keycloak token...');
console.log(tokErr);
})
getKeycloakAccessToken(){
const url = 'http://keycloak-keycloak.router.default.svc.cluster.local.......nip.io/auth/realms/myRealm/protocol/openid-connect/token';
const authH = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
const body = new HttpParams()
.set('username', 'sample')
.set('password', 'sample')
.set('grant_type', 'password').set('client_id','rest-client');
return this.http.post(url, body,{headers:authH,observe:'response'});
}
getKeycloakRoles(access_token){
const url = 'http://keycloak-keycloak.router.default.svc.cluster.local........nip.io/auth/admin/realms/myRealm/roles'
const authH = new HttpHeaders().set('Authorization','Bearer ' + access_token);// ({'Authorization':'Bearer ' + access_token});
return this.http.get(url,{headers:authH,observe:'response'});
}
and when I tried to debug, the access_token shown in console is different from that of request headers
[![network log][2]][2]
After debugging for couple of days, I figured out the reason for the difference in Access token, the API call is being invoked with the access_token of logged in session, though the program has source code written to set the headers set with access token of user 'sample/sample'. is there any way to trigger the API with the given access_token rather with the logged in user's access_token.
This might not be the solution, but just a couple of workarounds that worked for me.
Allow permissions (set 'Relam Management') to all the logged in users from the key cloak admin console, this way irrespective of user, whoever logs in will be able access the rest Admin APIs, follow this below
reference
From keycloak client library, we have a initializeKeycloak() , that has configurations set for the application, so disable the 'enableBearerInterceptor' which will say the application not to use the access_token generated by logged in user to set the headers of each request. this way we can avoid the forbidden error.
But with approach no.2, you can not use the AT of logged in user as we r disabling the enableBearerInterceptor.
And with solution no.1, if you are not having control on who are the users logging in to your application, i,e using some third party tool like LDAP to set the users, then it this won't serve the solution.
is it possible to use only the firebase auth and then create an own api with own database?
So I write an REST API which uses the firebase token to authentificate.
Thanks!
It depends on the technology that you will be using for the backend API. There is a Firebase Admin SDK, that is aimed at Java, Python and Node developers, but I think the functionality that you are looking for is only available in the Node SDK (although I believe that there are workarounds for this).
The way this works is that after your user signs in on the client side, they can request a token using firebase.auth().currentUser.getIdToken() which can then be passed to your backend which can then be verified, see the below example for how it could be done using Node and Restify.
const server = restify.createServer({});
server.use(validateJwt);
function validateJwt(req, res, next) {
if(!req.headers.token){
//reject
}
admin.auth().verifyIdToken(req.headers.token).then(decodedToken=>{
console.log(`token for user ${decodedToken.sub} valid`);
admin.auth().getUser(decodedToken.sub).then(user=>{
console.log(`fetched user ${user.email}`);
next();
}).catch(err=>{
res.send(500, 'the user with the ID does not exist in firebase');
})
}).catch(err=>{
console.log(`token validation failed: ${err}`);
res.send(401, 'authentication failed')});
}
I believe you should be able to do this, by using Firebase to authorise the user and then allow read access to a link securely stored for authenticated users only. This could then link to the database, if this is what you mean. I'd assume you may have already started here, but this is where to start Understand Firebase Realtime Database Rules
I've got a Meteor application with a multi-phase sign-up process. The accounts are based on the accounts-password package. In the step prior to account creation, the user needs to provide some profile information.
I'd like the user to be able to launch a Facebook OAuth flow which pre-populates the profile fields with information pulled from Facebook.
This all needs to happen pre-account-creation. I want to implement this with the facebook package that backs accounts-facebook.
At the moment I've got the OAuth flow happening by calling Facebook.requestCredential, but I'm not sure how to get an OAuth access token from the credential token that comes back. I suspect I need to pass this to the server and make an API call to get back an access token.
Any pointers as to how this should work would be much appreciated.
Facebook.requestCredential(function (credentialTokenOrError) {
if (credentialTokenOrError && credentialTokenOrError instanceof Error) {
// Error...
console.log(credentialTokenOrError);
} else {
// Credential Token string
console.log(credentialTokenOrError);
// Now perhaps a Meteor.call to a server method that
// 1. Retrieves an access token
// 2. Hits the graph API to get profile information and returns it to the client
}
});
Thanks,
Chris
I was having the same trouble of converting a credentialToken to an accessToken, only with Github. I've written up a gist that has code that should work very similarly. Essentially, there are two steps:
Within your Facebook.requestCredential callback function, call OAuth._retrieveCredentialSecret(tokenOrError), the result of which is the credentialSecret. Then use Meteor.call, passing in tokenOrError and credentialSecret, to call the Meteor.method you'll set up in the next step.
code (on client):
Github.requestCredential({
loginStyle: 'popup',
requestPermissions: ['gist']
}, function(tokenOrError) {
if (tokenOrError && tokenOrError instanceof Error) {
// Throw a Meteor error
console.log('error getting the token');
return;
}
var credentialSecret = OAuth._retrieveCredentialSecret(tokenOrError);
Meteor.call('getGithubAccessToken', tokenOrError, credentialSecret, function(err, accessToken) {});
});
On the server, set up a Meteor.method that takes your credentialToken and credentialSecret and calls Facebook.retrieveCredential. This function returns a credentials object from the _pendingCredentials Mongo Collection before deleting it from the collection. The access token is credentials.serviceData.accessToken. The credentials object could potentially be persisted in the user object in the Meteor.users collection (as it is in the accounts packages) or sent back to the user.
code (on server):
Meteor.methods({
getGithubAccessToken: function(credentialToken, credentialSecret) {
var credentials = Github.retrieveCredential(credentialToken, credentialSecret);
console.log('accessToken:', credentials.serviceData.accessToken);
return credentials.serviceData.accessToken;
}
});
I'm unfamiliar with the specifics of Facebook's Graph API so after these steps, you're on your own. Good luck!
In the Facebook dev article Manually Building a Login Flow, there is a section entitled "Confirming Identity". It mentions that you need to validate codes and tokens that you receive from them via your redirect_uri.
My question: Since you don't know anything about the user that just logged in, how do you validate that the user_id that you see in the response from the token inspection endpoint is correct?
The article says:
As a result, your app should confirm that the person using the app is the same person that you have response data for before generating an access token for them.
But, how can you actually do that? Are we expected to show publicly available info about that user_id back to the user with a UI that asks "Is this you?". I haven't seen any apps/sites that do that, so I'm assuming that this isn't practically done.
Am I missing something?
You can use FB.getLoginStatus to retrieve information about the logged in user. It returns a response object for the user. If the user has authenticated your application, the response object will look like this:
{
status: 'connected',
authResponse: {
accessToken: '...',
expiresIn:'...',
signedRequest:'...',
userID:'...'
}
}
You can use the UserId returned in this object to verify the user's identity.
I created a Meteor app that allows users to sign on using Facebook. To do this, I'm using the accounts-ui and accounts-facebook packages. This works fine.
How do I retrieve the user's email address once they've signed on? I understand that this requires special permission, and so I added email as a "User & Friend's Permission" in the app settings on the Facebook developers site. Following the Meteor documentation, I also set up Account.ui.config like this:
Accounts.ui.config({
requestPermissions: {
facebook: ['email'],
},
passwordSignupFields: 'USERNAME_AND_EMAIL'
});
As expected, when a user of my app signs on using Facebook, it correctly asks them to share their email address. But how do I retrieve it? The user document has only the _id and profile.name.
The Facebook user's email address is stored in [userDocument].services.facebook.email, which is not published to the client, but can be accessed from the server or from the client using Meteor.methods and Meteor.call.
this will add the Facebook profile info to the client side user object.
Accounts.onCreateUser (options, user) ->
if options.profile
user.profile = options.profile
# get profile data from Facebook
result = Meteor.http.get "https://graph.facebook.com/me", {
params: access_token: user.services.facebook.accessToken}
if !result.error && result.data
#if successfully obtained facebook profile, save it off
#the user can access the profile object on the client
user.profile.facebook = result.data;
return user
on the server side the facebook.accesstoken can be accessed... so use it to get the full FB info and save it to the client user object..
ping a Meteor.user() in the console now to get the FB info.
dont think this is exactly best practice in terms of having FB info on the client..