Consume Saml Response from external identity provider - javascript

I am having trouble configuring my application to consume the SAML response from an external identity provider (in this case, OneLogin). My application has a javascript (angular5) front-end and .NET back-end.
Here is our current work-flow when using our own identity provider and service provider.
User navigates to our application in the browser and receives a 401 unauthorized when requesting resources from the API.
User is redirected to the login page.
User enters credentials which are posted to our server-side identity provider.
If the user is authenticated, the identity provider returns a SAML response to the client.
Client posts the SAML response to the service provider.
Service provider returns the tokens needed to access the rest of the API.
Now a customer has requested we integrate their external identity provider using OneLogin. Here is what I understand to be the new workflow.
User navigates to our application in the browser and receives a 401 unauthorized when requesting resources from the API.
User is redirected to the OneLogin (external identity provider) page.
User enters credentials which are authenticated by OneLogin.
OneLogin will post to our provided service provider endpoint with the SAML response as Form Data in the HTTP Post.
If post is successful the user will be redirected to any url provided when configuring OneLogin.
?????? (Our front-end still has no idea who the user is or whether or not they are authenticated).
Currently, all communication between our angular front-end (client) and .NET back-end (server) is initiated by the client. What I really need is for the client to receive that SAML response form data that is posted by OneLogin, so that I can initiate authorization with our service provider and receive the appropriate response in the client, but from what I understand I won't be able to consume the Form Data client side. I was hoping I could have the external identity provider redirect to a page on our front end and encode that saml response as a query parameter, but I am not seeing any way to do that.
I feel like there is something I am missing, but all the OneLogin examples seem to be the OneLogin identity provider communicating with a server side service provider and no mention of the client side. I could use some help better understanding what I need to do to accomplish my goal of informing the client that the user is authenticated and authorized.

What you describe with OneLogin is the SAML2 Web Browser SSO profile. As you see, it's all done through the browser. The user gets redirected from the client to the IdP, where they login. The IdP then POSTs a SAMLResponse to your Attribute Consumer Service (ACS) URL at your back end. It's the ACS's job to decode the SAMLResponse and parse the SAML2 attributes contained within it. It can create a new session at that point if required.
At this point the back end now knows who the user is. So you can initiate another redirect to send the browser to another URL with a parameter that lets the client know it has to retrieve user details from the back end. Perhaps some sort of /sso?token=something URL. The client side can then ask the back end to return JSON perhaps that contains the user information referenced by token, i.e. a session of some sort the back end has created once the attributes have been verfied.

Related

How to share auth0 authentication information between 2 different APIs?

Pretty much new on APIs and microservice world.
i am using auth0 for authentication.
I have a convert express API POST endpoint which will only work if the user is authenticated, however for frontend -> ( home page, login button, login from auth0 callback, redirection) I using different api Homepage express api.
After user logs in from homepage api, from his profile dashboard user tries to send a post request to convert API endpoint this doesn't work and throws an error check.state argument is missing.
How do I make sure if one API authenticates that authentication information should be shared with another API endpoint which needs authentication?
app.use(‘/authUrls’,requiresAuth(),authUrlsRouter) //convert api post request
This may be an assumption, but it appears that you are creating a regular web application with Node.js, and what you want is authentication per session, not per API endpoint. This quickstart from Auth0 walks through it nicely. It uses Passport.js and express-session to provide middleware.
As per the tutorial:
In a typical web application, the credentials used to authenticate a user are only transmitted during the login request. If authentication succeeds, a session is established and maintained via a cookie set in the user's browser. Each subsequent request does not contain credentials, but rather the unique cookie that identifies the session.
How it works: when the login api is called and completed successfully, the user's authentication is stored in that session. Whenever other API's are called that require an authenticated user, you can just include the middleware (in the quickstart it is called 'secured'): it will query that respective session's data and allow / disallow based on the user's authentication status.
For example, the convert endpoint:
router.post('/convert', secured(), this.convertfunction);
And a non-auth endpoint:
router.get('/other', this.otherfunction);
The full tutorial has much more information available. But this illustrates how middleware will solve your problem.

Authenticating a User against a client in Keycloak

I have a Keycloak server setup with a realm and a client. I have Authorization setup on the client and I'm able to evaluate the authentication within the admin interface.
When I click "Show authorization data", I can see in the response an authorization attribute with permissions.
I have a web client that uses a redirect via keycloak for oidc authentication. I would like to limit which keyclock users are able to login into the client, so I would like to authorise the login, but I'm unable to see the authorization attribute in the JWT.
Am I completely misunderstanding how this works, or is there something I can do to see that attribute?
OK, I've finally go my head around it. Short answer - I needed to RTFM.
Long answer - I needed to hit the token endpoint twice. The first time with grant_type = authorization_code to get the access token. Then again with grant_type = urn:ietf:params:oauth:grant-type:uma-ticket (and with the access token in the header) to get the keycloak client to authenticate.
If the second response comes back as 403 - access_denied, then I reject the login, otherwise, I allow the user to login into my system.
The specific bit I needed can be found in the docs is here: https://www.keycloak.org/docs/6.0/authorization_services/#_service_obtaining_permissions

OAuth 2.0 Implicit Grant Type with AngularJS frontend

I'm currently building a frontend client for my own Apigility API.
The API uses OAuth 2.0 Authentication which is working fine.
I want to create an AngularJS Landingpage to let the users authenticate by entering their credentials. Because the Client is created with JavaScript,
I shouldn't save the client_secret in the Client, correct?
I have read a lot of posts, but still haven't the right solution.
Is it correct to use the implicit grant type for this scenario?
This procedure is working, I'm being redirected to the authentication server,
after the client authorization and entering credentials, I get back to the client (authenticated).
But I don't want to get redirected to another authentication page.
Is it also possible to authenticate directly and secure on the angularJS frontend?
Thanks,
Simon
You should take a look at this post i made:
https://stackoverflow.com/a/42443878/2963703
It details how to do this using the Spotify API. Your page won't get redirected, instead a popup window will open in which the user authorizes themselves. Once they're authorized the window will close itself and in your main page you will have the access token you need.

How to safely communicate between a JS app and an OAuth2.0 server hosted on the same domain?

I know the issue of securing connexion between a JS app (let's say just 'app') and an OAuth2.0 server (let's say just 'server') is an age-old question.
However, I can not find a lot of information about the special case where the app and the server are coded by the same entity and stored at the same place (i.e. same domain, or at least, two subdomains of the same domain).
First of all, as far as the OAuth grant type is concerned, I think the right one is the Resource Owner Password Credentials Grant, since the server and the app have the same author. The issue here being that the Client ID and Client Secret are available to the user in the client. This can be dealt with either by developing a proxy on server end or by using short-life tokens and disabling CORS (if I understood correctly). Is there any other property we can take advantage of as far as security is concerned when server and app have the same author?
My second question relates to the optional use of a Facebook Login authentication (or whatever well-known app OAuth login system: Google, Twitter, etc.).
Ideally, I want users to log in using either:
My-app-related credentials (if they registered without using FB login option)
Facebook credentials (if they registered using FB login option)
The first log in method is the classical one: upon log in, are sent to the server the user credentials along with the client ID and client Secret, we get back an access token and everything works well.
I must confess I'm a bit lost with the second method: upon login, user Facebook credentials are sent to Facebook server, which responds with an access token, and my app get access to my user Facebook information (such as email address and UID). But I do not know what to do with this FB information, and especially what I should sent to my own OAuth server so that:
The user gets connected to my server
The connection is secure (i.e. no one can impersonate the user by only having to get her Facebook UID for instance).
In other terms, there should be something secret related to Facebook sent to my server but I can not figure what.
I have found the answer to my second question, so I share it here:
What should be passed on to the server is the Facebook access token, so that the server can :
make a request using Facebook PHP SDK and the given token
retrieve user data (such as Facebook UID for instance)
match it against your website user database (which should have users FB UIDs)
actually connects the user if there is a match
Step 1. and 2. can be done nicely with the helper class FacebookJavascriptLoginHelper of the FB PHP SDK. In this case, the access token is stored by Facebook Javascript SDK into a cookie that is read server-side by the FacebookJavascriptLoginHelper.

How to get access token and refresh token after user login and consent in Google OAuth2?

I want to import contacts of a Gmail user through the Google API.
I have the following:
Use Client secret and key to obtain the authorized url. This is the url which the user visits to allow permission for my app.
The authorized url redirects to the redirect uri specified in the App settings.
I have a query parameter code in the url and I am guessing this is the Authorized code that the docs say here.
The problem:
I want to exchange this code to obtain the access token and the refresh token through javascript if possible. But I can't see any docs for this part in javascript.
In my server side I am doing this to obtain the authorized url:
token = gdata.gauth.OAuth2Token(client_id=settings.GMAIL_CLIENT_ID,
client_secret=settings.GMAIL_API_KEY,
scope=scope, user_agent=user_agent)
auth_url = token.generate_authorize_url(redirect_uri=redirect_uri)
and then redirecting the user to auth_url. Now once the user is allowing the requested permissions they are redirected back to my site with the query parameter code. I want to use javascript from here to get the access token.
The other option is to get the access token in the server side once the user is redirected to my site and return it to him along with the response but I dont really want to do this.
Short answer: if you want to use OAuth2 client-side authentication, you're using the wrong documentation.
Now the details.
OAuth2 has 4 grant types:
Authorization Code,
Implicit,
Resource Owner Password Credentials and
Client Credentials
If you want more details, you can read this nice post with explanation.
You've pointed the Google docs for OAuth2 for Web Servers, which fits Authorization Code type. It relies on Web Server data exchange over SSL, because it involves exchange the client_secret.
I.e, if you try do the POST request to get the access_token using JavaScript, you'll expose your client_secret, as it's a required parameter in the POST call.
If you want try request the access_token not using server side code, you need to use the Implicit grant type.
You can find Google documentation for Implicit grant type in Using OAuth 2.0 for Client-side Applications

Categories

Resources