OpenID Connect with embedded resources - oauth-2.0

The setup is: we have our user. Our authentication platform (the authorization server). And two different resources. Code authorization flow is used in our setup.
Now resource A embeds stuff from resource B in its pages (with something like an iFrame). Now what we'd like to accomplish is that once the user is authorized for resource A that he will transparantly be able to access the embedded resources from resource B.
Is this possible? If so how?

If the authorization server supports Single Sign On (SSO), the embedded page could get its tokens without the user having to enter their credentials. The steps would be like this:
User requests Resource A
Resource A redirects the user to the OAuth2 server to get tokens
The OAuth2 server creates a session for the user (identified by a browser cookie)
The user passes authentication and gets redirected to the Resource A page
The Resource A page requests Resource B page, so the Resource B goes to point 2, but the point 4 is skipped, because the OAuth2 server already has a session for the user and doesn't ask for the authentication anymore.
Or if your applications don't need access_tokens, just ID tokens, you could pass it from the Resource A to Resource B (e.g. as a URL parameter). In such case, ID tokens should contain both clients (Resource A and B) in its aud (audience) parameter.

Related

Using a third party site for OAuth2 / OIDC authorization code flow- understanding the final steps

I've a site which will hopefully use a third party service for logging in (through use of OAuth2 and OIDC). I understand 90% of the process involved but am failing to get what I see as the final step. I'll describe the steps as I see them here and maybe someone can help me fill in the gaps. In my set up the Resource Server and Authorisation servers are the same machine.
This is the login process as I envisage it.
User comes to my site (let's call it Site A) and clicks login
They're redirected to the authentication site (Site B) where they
input their username / password.
Assuming correct credentials they're then redirected back to Site A with an auth code.
Site A takes this auth code and in a back channel communicates with Site B
again asking to exchange the code for a token.
Site B provides an access token to Site A (not to the end user, to the server)
Site A then communicates with Site B again (Resource and Authentication servers are the same in this scenario) and gets the relevant user detail.
So the user is authenticated and we know what claims they have, however, what I don't get in the above scenario is how Site A knows who I (the end user) am.
I never logged in on Site A so presumably no cookie was set. Basically I've gone to the site, been redirected to another site, logged in there and then am redirected back to Site A but is there a cookie set at that last redirect to identify me?
I've read plenty about this online but haven't found a clear answer.
Also, am I correct in thinking that in authorization code flow that the access token never gets to the user but instead resides on the application server?
If you really want to know who the user is on SiteA, it has to be the user from SiteA's own user database. It makes sense if SiteA is not just a proxy for SiteB's API and has its own users, permissions and functionality.
To figure out who the user is on SiteA you will need to match all your SiteA's users with Auth Server's users.
Part 1. Import your existing users into Auth Server
If you control Auth Server, import all your current users into its user database. Every one of them will have Subject ID (Id on Auth Server side). Copy those IDs back to corresponding users in your SiteA's db: your SiteA's User table will have new column, for example:
userid, user_name, user_last_name, user_auth_id (new column)
if you can't import all your users, it gets complicated. The only way I can think of: you will have to log those users in twice - once into OIDC provider and once in SiteA and then associate SiteA's user with OIDC user.
Part 2. Matching the incoming user to the internal user in SiteA
In successful response from OIDC Server you will get ID Token back. It contains sub claim with Subject ID of the user. When you've got that, you will need to do a lookup in your internal DB and find a corresponding SiteA's user. If you did not find one, create a new user at SiteA (if all existing users had been imported)
Once you know who the user is, log them in to SiteA like you would normally do (give them a cookie for example).
OpenID Connect auth servers provide the userinfo endpoint, which Site A can use for getting info about the user who authorized the access token (or the authorization code). For the auth provider (Site B) to be able to do it, it needs to keep association between a token and its user. So there is no cookie for this purpose.
You are correct about the auth code flow - the access token stays at the backend - there is no need to send it to the frontend / user.
To be able to pair the tokens kept at the SiteA backend with the consequent requests from the browser, you have few options:
You can use a backend session with cookies, which is very easy, because most backend frameworks have a built-in support for it. The cookie is sent automatically with each request and the tokens can be stored in a session object. This solution may be harder to scale - if you need a cluster.
You can create your own session implementation - either by using cookies or by some identifier expected on REST API as the Authorization HTTP header value. The backend session data can be kept in some distributed storage, such as Hazelcast or database. The session identifier can be in form of signed JWT, so you can keep user info in it.

How to handle user registration in OAuth Server when it is separated from the Resource Server?

I am working on an application in which users with elevated roles (administrators) can create other users (with lower roles). I'm using PHP (Slim framework) and MySQL.
So far i have a Resource Server which can be accessed through a REST API with access tokens obtained from the OAuth Server using the Password Grant. The two servers have separate databases. There is also a Web Server which provides a dashboard where administrators log in and create new users by setting their username, password and other generic information.
Considering the fact that both the Resource Server and the OAuth Server have to store user data in their respective db tables, would it be ok if the Resource Server, upon a new user request, stores the generic user info in it's "users" table AND sends a request with the user credentials to the OAuth Server which will add a new entry in it's "oauth_users" table ? If not, what would be the best and secure way to achieve this functionality ?
Thank you in advance!
This approach works for us.
On the Auth Server db side you have to store only: user id, redirect url's and authorized service level (scopes) configured; the access tokens granted; and other authorization required data (roles in your case).
The Login Server db, stores: user id, password and other authentication related data.
The User resource service (commonly a RESTFul API) should store: user id and other personal data.
Upon a new user request of a secured resource data (some scope is needed here), redirects to the Login Server, with this successful authentication, redirects to the Auth Server to grant permissions using that scope, generate an access token and redirect to the secured resource with an access token, the resource server validates the token and the scope (some implementations also make another call to the Auth Server to validate this using JWT) to finally allow the initial user request.
In general, I personally use the DRY principle with this kind of architecture.
Cheers!

Difference between the “Resource Owner Password Flow” and the “Implicit grant”

The implicit grant is a simplified authorization code flow optimized
for clients implemented in a browser using a scripting language such
as JavaScript.
The resource owner password credentials (i.e., username and password)
can be used directly as an authorization grant to obtain an access
token.
(https://www.rfc-editor.org/rfc/rfc6749#section-1.2)
My question is about understanding how these two grant types are different?
Important to understand here is the way and place you enter your credentials.
Implicit
Your app is https://example.com and for authentication, you are going to https://auth.some-domain.com (or even https://auth.example.com). After successful authentication, user is redirected to https://example.com/some-callbackurl?#token=token-value.
Points to be noted: Redirection and token in URL
Resource Owner Password flow
Your app is https://example.com and for authentication, you are going to https://example.com (or https://example.com/login). After successful authentication, user is redirected to https://example.com/home.
Points to be noted: No redirection and no token exchange in URL
Basically if you are owning the app (client app, server app, auth app) then this is something you would do. Basically you are the one who is in charge of authentication - not a third party app. You trust your client app.
https://example.com/login gets credentials from user and does a HTTP REST POST (for example) call and get a response as token (and refresh token - optionally). It saves it in localStorage or cookie and then redirects to home page or whatever page it has to redirect to.
No redirection happens in exchange.
As you quoted, the "Resource Owner Password Credentials Grant" is suitable in cases where the resource owner has a trust relationship with the client, such as the device operating system. An example is Facebook application - Facebook trusts their app that is installed on the device.
Thus, client-app does not have to be registered in the auth-server. As you can see in the request the client_id is not transferred as a param. In addition, the flow is simpler - the access token is retrieved within a single request.

In resource owner password flow, can user handle the scope?

I am using Identity Server 4 for authenticate user from a single application page. For the need of the project, I have to use the resource owner password flow.
Identity Server and my application work fine together. Identity Server give an Access Token and I can use this token to access some API that we own.
However, I was asking myself about the Access Token, users and socpes. For now my setup is this one.
I have an API that require the scope API-1.
I have a client (my SPA) where I defined the scope API-1
And I have a user.
In this configuration, it is the client who own the right to access the API, not the user. And I'm wondering how to give this scope to the user and not anymore to the client.
Stupidly, I'm wondering if user can own the scope and not the client. Maybe I've miss or misunderstood something, so please teach me.
In the Resource Owner Password Flow your client will always need to have permission to the scope that your resource is protected by. This does not mean that you cannot protect your API based on claims related to the user however.
If in your API for example you need different permissions based on the user accessing the API look to use the claims information as part of your authorization. In the Resource Owner Password Flow example at http://docs.identityserver.io/en/release/quickstarts/2_resource_owner_passwords.html you will see that it mentions this at the foot of the page, see the two paragraphs as follows:
When you send the token to the identity API endpoint, you will notice one small but important difference compared to the client credentials grant. The access token will now contain a sub claim which uniquely identifies the user. This “sub” claim can be seen by examining the content variable after the call to the API and also will be displayed on the screen by the console application.
The presence (or absence) of the sub claim let’s the API distinguish between calls on behalf of clients and calls on behalf of users.

Simple active federation from third-party id providers

I have a secure web application that I wish to expose to partners so their clients can capture information directly into a form hosted on my application.
The form will be shown in an iframe embedded within the partners web application. The URL of the iframe will point to my application and contain some form of session token that I issued to the partner before they rendered the iframe.
I don't want to store the user's credentials in my app I just need a mechanism to validate with the partner that the user is authenticated by them and authorised to perform the action I am hosting.
I have looked at SAML and oAuth but both seem incredibly complex for the identity provider to implement. I'd rather implement most of the complexity myself and provide the partner with an easy means of integrating.
i.e. The key is finding a solution that is simple for the identity provider
Example:
Partner requests a session token from me via some predefined endpoint (they would specify the action that their user will need to perform, the user's username or id and client token to validate the response).
https://myapp.com/getsession/?username=bob&action=action1&token=CLIENT_SESSION_TOKEN
I return a SERVICE_SESSION_TOKEN.
Partner embeds iframe with the following URL in their app:
https://myapp.com/action1/?username=bob&token=SERVICE_SESSION_TOKEN
I validate the token and create an authenticated session for the user with authority to perform action1.
I return the form for action1 and it is rendered in the iframe.
When the user submits the form I can notify the partner of this by redirecting the iframe to
https://partner.com/action1_callback/?username=bob&token=CLIENT_SESSION_TOKEN&result=RESULT
Is there a standard that supports such a protocol? oAuth and SAML make the identity provision very complex.
Have you looked at Simple Web Token (SWT)? The token has a simple format like for example:
Issuer=partner.com&ExpiresOn=1262304000&Username=Bob&ClientSessionToken=B2202256-76A6-4527-8439-E6C3F017F414&HMACSHA256=AT55%2B2jLQeuigpg0xm%2Fvn7tjpSGXBUfFe0UXb0%2F9opE%3D
There is only one required parameter HMACSHA256 which secures the token from tampering.
Issuer and ExpiresOn parameters recommended to use to identify the issuer of the token and restrict the time of token validity. Other parameters depend on the information you need to pass in the token.

Resources