At work we have never used 3rd party Auth solutions and I'm trying to inform myself of how they work for my personal projects. Getting the response is easy enough, but feel a bit lost on what to do after I get the response back. Am I supposed to send the auth token to the backend so it can be verified then trigger my app's login process for the given e-mail address/username? Logging them in essentially without a password?
There's two basic use cases for OAuth 2.0 which will determine what you do after the user is authorized. Your use case can also determine which OAuth 2.0 permission scopes you request the user to authorize your app for.
1. Single Sign-on
A simple use case for using a 3rd party OAuth solution is to leverage the 3rd party to perform authentication. Two reasons for this include:
Your users may wish the convenience of logging in with another provider (like Google, Facebook, Twitter, etc.), one where he or she may already have an active session.
You may not wish to implement your own login / authentication / password reset process.
Either way, a common way to implement this is to make an API request using the token to retrieve the user's email address after a successful authentication, which you then map to your own user database to establish an authenticated session for your service. Since you only need to retrieve the user's email address and minimal other information (e.g. name) in this use case, you can ask for a minimal set of scopes.
I do this in my oauth2more library where after receiving a token, I have a generic interface to load a user data which I convert to a SCIM user object. Because I've abstracted the code to retrieve user info in this manner, it's easy to support SSO across mulitple auth providers.
2. Using Service Features
A slightly different use case is that you want the user to authorize your app so you can make commands on behalf of the user via API. In this case, you will use the token to call more general APIs to accomplish your goals. A caveat is that you will need to make sure you ask for the proper permissions when asking the user to authorize your app.
As an example, one thing I've done is ask the user to sign in with Google so I can then make API calls to create and edit Google Sheets and Google Slides using APIs on their behalf.
In our project, we are using oauth (implementation - apifest) for token generation and validation. I am unable to understand the scope concept.
As per my understanding, oauth scope is used for authorization, which consists of some permission.
We have capability and role concept in our project, where:
Capability - permissions
Role - group of capabilities.
A role will be assigned to a user, based on which he functionality across application will be defined.
Role creation is dynamic.
Is this role concept the same in oauth? or is the scope defined at application level, where the users in that application will have the same scope?
I tend to think of Scopes as a permission (or entitlement) to perform some action.
A role is typically a collection of permissions required to perform a "Job" or work within a "Project"
OAuth has no concept of a "Role"
Scopes are Requested by the client but are only Granted by the Authorization Server.
Scopes requested may not be granted and additional scopes may be granted that were not requested.
Scopes are used to delimit which applications can act on the behalf of the resource owner.
If you have an application, say a voting service, at voting.example.com. You have two roles: voters, which can see a poll, and vote, and admins, which can see the full results. The voting application enforces permissions based on these roles. A local user is assigned a local role. The application is protected using OAuth, so a user can be identified by a token.
You also have a social network app, social.example.com. This app provides a page where users can vote on the voting service. It is also connected to the same OAuth authorization server.
Finally, someone else has a reporting app, reports.example.com. This app would like to allow users to see the vote tally by requesting it from the voting service. It is connected to the same authorization server.
The authorization server, say iam.example.com. The authorization server has three clients, one for each app described above. There are two scopes defined in the authorization server, voting, and reporting.
The reporting app, when you login will request the reporting scope. The actual login happens on iam.example.com which will grant the token to reports.example.com. The login form will ask you, the user, whether you grant the client (reports.example.com) the right to act on your behalf and obtain reports from the voting service (provided by the reports scope). The scope will be recorded and associated with the token it sends to reports.example.com.
Now the reporting app can make a request to voting.example.com which says, "I would like to see the voting tally" The voting.example.com app will check the token, and provided it has the reports scope, it will send back the tally.
If it tries to make a request to the voting service to vote, it should be refused by voting.example.com, because the bearer token does not have the scope allowing you to vote. This must be enforced by the voting app. The authorization server manages which client is granted which scope. Only to see the reports. This is not related to your role in the voting application itself.
OAuth itself doesn't provide a mechanism for identity validation, so you do not have a mechanism for validating who you are from the token, and what roles you have. OpendID connect (OIDC) provides extra functionality for this by providing a scoped based identity endpoint protected by the authorization endpoint which allows it to reveal your identity to the app. So if we assume you have OIDC too, then it will check, from the token, who you are. It can then check it's database to see whether you have the right role, and whether you are allowed to see the tally before sending it.
What the scope enforces, is that the reports app, using it's client, can obtain a token to act on your behalf and ask for the information. When you grant the client the scope, you are allowing it to communicate with the voting service to obtain the information.
Roles are managed by your application and with a permission system, determine who can vote, who can read the votes.
Using something like OIDC, you can extend OAuth so the token identifies who you are. voting.example.com can then check that you are a) authorized to vote (by the local logic), b) that the application doing it on your behalf is allowed to act on your behalf (through the scope attached to the token).
For the past 10+ days I've read an watched ALL the content I could find on understanding OAuth2 and OpenID Connect, only to find that many people disagree on the implementation, which really confuses me.
To my understanding, all the articles and examples I found assume you want access to eg. google calendar, profile info or emails if you eg. login with google, but I do NOT need to access other than my own API's - I only want to use Google, Facebook etc for logging in, and getting an id which I can link to my user in my own database - nothing more than that.
I'll try illustrate my use case and use that as an example.
A note on the diagram: the Authentication service could probably be built into the API Gateway - not that i matters for this example, since this is not about "where to do it", but "how to do it the best way" possible, for an architecture such as mine, where it's used for my own API's / Microservices, and not accessing Google, Facebook etc. external API's
If you can understand what I'm trying to illustrate with this diagram above, please tell me if I've misunderstood this.
The most basic requirements for this architecture you see here are:
Users can login with Google, Facebook, etc.
The same login will be used for all micro-services
OpenId user will have a linked account in the database
User access is defined in my own db, based on groups, roles and permissions
I do not intend to use external API's after the user is authenticated and logged in. No need for ever accessing a users calendar, email etc. so I really just need the authentication part and nothing else (proof of successful login). All user access is defined in my own database.
So a few fundamental questions comes to mind.
First of all, is OpenID Connect even the right tool for the job for authentication only (I'll have no use for authorization, since I will not need read/write access to google / facebook API's other than getting the ID from authenticating)?
People generally do not agree on whether to use the ID or Access token for accessing your own API's. As far as I understand the ID token is for the client (user-agent) only, and the access token is for eg. accessing google calendar, emails etc.... External API's of the OpenID Provider... but since I'll only be accessing my own API's, do I event need the access token or the ID token - what is the correct way to protect your own API's?
If the ID token is really just for the client, so it can show eg. currently logged in user, without going to the DB, I have 0 use for it, since I'll probably query the user from from the db and store it in redux for my react frontend app.
Dilemma: To store user details, groups, roles and permission inside JWT or not for API authorization?
By only storing the user identifier in the token, it means that I always allow authenticated users that has a valid token, to call endpoints BEFORE authorization and first then determine access based on the db query result and the permissions in my own database.
By storing more data about the user inside the JWT, it means that in some cases, I'd be able to do the authorization / access (group, role, permission) check before hitting the API - only possible with user info, groups, roles and permission stored inside a JWT issued upon login. In some cases it would not be possible due to eg. the CMS content access permissions being on a per-node level. But still it would mean a little better performance.
As you can see on the diagram I'm sending all API requests through the gateway, which will (in itself or with an authentication service) translate the opaque access token into some JWT with an identifier, so I can identify the user in the graph database - and then verify if the user has the required groups, roles and permissions - not from an external API, but from my own database like you see on the diagram.
This seems like a lot of work on every request, even if the services can share the JWT in case multiple services should need to cross call each other.
The advantage of always looking up the user, and his permissions in the db, is naturally that the moment the user access levels change, he is denied/granted access immediately and it will always be in sync. If I store the user details, groups, roles and permission inside a JWT and persist that in the client localstorage, I guess it could pose a security issue right, and it would be pretty hard to update the user info, groups, roles and permissions inside that JWT?
One big advantage of storing user access levels and info inside the JWT is of course that in many cases I'd be able to block the user from calling certain API's, instead of having to determine access after a db lookup.
So the whole token translation thing means increased security at the cost of performance, but is is generally recommended and worth it? Or is it safe enough to store user info and groups, roles, permissions inside the JWT?
If yes, do I store all that information from my own DB in the ID Token, Access token or a 3rd token - what token is sent to the API and determines if the user should be granted access to a given resource based on his permissions in the db? Do I really need an access token if I don't need to interact with the ID providers API? Or do I store and append all my groups, roles, permissions inside the ID token (that doesn't seem clean to me) issued by OpenID connect, and call the API and authorize my own API endpoints using that, even if some say you should never use the ID token to access an API? Or do I create a new JWT to store all the info fetched from my database, which is to be used for deciding if the user can access a given resource / API endpoint?
Please do not just link to general specs or general info, since I've already read it all - I just failed to understand how to apply all that info to my actual use case (the diagram above). Try to please be as concrete as possible.
Made another attempt to try and simply the flow:
The following answer does only apply for a OpenID Connect authentication flow with a 3rd party IDP (like Google). It does not apply for an architecture where you host your own IDP.
(There are some API gateways (e.g Tyk or Kong) which support OpenID Connect out of the box.)
You can use JWTs (ID token) to secure your APIs. However, this has one disadvantage. JWTs cannot be revoked easily.
I would not recommend this. Instead you should implement an OAuth2 authorization server which issues access tokens for your API. (In this case, you have two OAuth2 flows. One for authentication and one for authorization. The ID and access token from the IDP are used only for authentication.)
The following picture shows a setup where the API gateway and authentication/authorization server are two separate services. (As mentioned above, the authentication/authorization can also be done by the API gateway.)
The authentication flow (Authorization Code Grant) calls are marked blue. The authorization flow (Implicit Grant) calls are marked green.
1: Your web app is loaded from the app server.
2a: The user clicks on your login button, your web app builds the authorization URL and opens it. (See: Authorization Request)
2b: Because the user hasn't authenticated and has no valid session with your authorization server, the URL he wanted to access is stored and your authorization server responds with a redirect to its login page.
3: The login page is loaded from your authorization server.
4a: The user clicks on "Login with ...".
4b: Your authorization server builds the IDP authorization URL and responds with a redirect to it. (See: Authentication Request)
5a: The IDP authorization URL is opend.
5b: Because the user hasn't authenticated and has no valid session with the IDP, the URL he wanted to access is stored and the IDP responds with a redirect to its login page.
6: The login page is loaded from the IDP.
7a: The user fills in his credentials and clicks on the login button.
7b: The IDP checks the credentials, creates a new session and responds with a redirect to the stored URL.
8a: The IDP authorization URL is opend again.
(The approval steps are ignored here for simplicity.)
8b: The IDP creates an authorization and responds with a redirect to the callback URL of your authorization server. (See: Authentication Response)
9a: The callback URL is opened.
9b: Your authorization server extracts the authorization code from the callback URL.
10a: Your authorization server calls the IDP's token endpoint, gets an ID and access token and validates the data in the ID token. (See: Token Request)
(10b: Your authorization server calls the IDP's user info endpoint if some needed claims aren't available in the ID token.)
11a/b: Your authorization server queries/creates the user in your service/DB, creates a new session and responds with a redirect to the stored URL.
12a: The authorization URL is opend again.
(The approval steps are ignored here for simplicity.)
12b/+13a/b: Your authorization server creates/gets the authorization (creates access token) and responds with a redirect to the callback URL of your web app. (See: Access Token Response)
14a: The callback URL is opened.
14b: Your web app extracts the access token from the callback URL.
15: Your web app makes an API call.
16/17/18: The API gateway checks the access token, exchanges the access token with an JWT (which contains user infos, ...) and forwards the call.
A setup where the authorization server calls the API gateway is also possible. In this case, after the authorization is done, the authorization server passes the access token and JWT to the API gateway. Here, however, everytime the user infos change the authorization server has to "inform" the API gateway.
This is a very long question. But I believe most can be summarised by answering below,
To my understanding, all the articles and examples I found assume you want access to eg. google calendar, profile info or emails if you eg. login with google,
You do not necessarily use Access token (ID token in some occasions) to access the services offered by token issuer.You can consume tokens by your own APIs. What these Identity Providers (synonym to Authorization server, or IDP in shorthand) is to hold identities of end users. For example, typical internet have a Facebook account. With OAuth and OpenID Connect, the same user get the ability to consume your API or any OAuth/OIDC accepted service. This reduce user profile creation for end users.
In corporate domain, OAuth and OIDC serves the same purpose. Having a single Azure AD account lets you to consume MS Word as well as Azure AD's OIDC will issue tokens which can be used to Authorise against an in-house API or an third party ERP product (used in organization) which support OIDC based authentication. Hope it's clear now
A note on the diagram is that the Authentication service could probably be built into the API Gateway - not sure if that would be better?
If you are planning to implement an API gateway, think twice. If things are small scale and if you think you can maintain it, then go ahead. But consider about API managers which could provide most of your required functionalities. I welcome you to read this article about WSO2 API manger and understand its capabilities (No I'm not working for them).
For example, that API manager has built in authentication handling mechanism for OAuth and OIDC. It can handle API authentication with simple set of configurations. With such solution you get rid of the requirement of implement everything.
What if you can't use an API manager and has to do it yourself
OpenID Connect is for authentication. Your application can validate the id token and authenticate end user. To access APIs through API Gateway, I think you should utilise Access token.
To validate the access token, you can use introspection endpoint of the identity provider. And to get user information, you can use user-info endpoint.
Once access token is validated, API gateway could create a session for a limited time (ideally to be less or equal to access token lifetime). Consequent requests should come with this session to accept by API gateway. Alternatively, you can still use validated access token. Since you validated it at the first call, you may cache for a certain time period thus avoiding round trips to validations.
To validate user details, permission and other grants, well you must wither bind user to a session or else associate user to access token from API gateway at token validation. I'm also not super clear about this as I have no idea on how your DB logic works.
First Appreciate your patience in writing a very valuable question in this forum
we too have same situation and problem
I want to go through ,as images are blocked in our company in detail
Was trying to draw paralles to similar one quoted in the book
Advance API In Practise - Prabath Siriwerdena [ page 269]Federating access to API's Chapter. Definitely worth reading of his works
API GW should invoke Token Exchange OAUTH2.0 Profile to IDP [ provided the IDP should support TOken Exchange profile for OAUTH 2.0
The Absence of API Gateway , will result in quite bespoke development
for Access Control for each API Check
you land up in having this check at each of the api or microservice [ either as library which does work for you as a reusable code]
definitely will become a choking point.]
Our team is starting to build out a SMART on FHIR (SoF) application. SoF uses OAuth2 access_tokens to represent authorizations. Our app is using the code grant to get a token (https://oauth2.thephpleague.com/authorization-server/auth-code-grant/).
I'm pretty new to OAuth2 (used to SAML) and have been reading up on the standard. I think we may be conflating what the access_token is intended to represent.
Is the intent in OAuth2 that the access_token represents the permissions the resource owner (end user) has granted to the client (web application) to perform on their behalf?
Or is the intent to rely that the resource owner (end user) is allowed to preform certain operations?
For example say the auth token request has a scope called 'contacts-update'. If we get an access_token back with this scope, does that mean the user has allowed the application to attempt to update contacts (on their behalf) or does it mean that the user has the underlying requirements (they are in the update contacts role) to be able to update contacts?
As you wrote, the OAuth2 access token represents a permission delegation from a resource owner to a client (application), so the client can perform operations on behalf of the resource owner. That's also why there is a consent page - the user agrees on giving the application permissions (scopes) it requested.
Sometimes, people want to use OAuth2 as a central authentication server and a permission configuration for their applications. They want each application to see all permissions the user has configured for it. Then it doesn't make sense for application to ask for specific scopes, but to configure the OAuth2 server to return all relevant for that application (identified by a client_id). But I don't think this is the intended way of usage and the OAuth2 specification doesn't cover this scenario.
OAuth2 can also be used for authentication only, if it supports OpenID Connect extension. Then applications can ask for ID tokens. ID token proves identity of a user and the permissions are handled in each application separately.
We are setting up a OAuth 2.0 via PingFederate in our organization. The scenario in question is as follows - We have a website in which the customer would be logging in using user name and password. There are are also links within the site to redirect the customer to a partner site. The partner site would be securely passed some basic information via SSO payload.
The partner site would also need to be able to call back to our Apis (call made in the background) to get additional information about our customer which they will then use to display on their site.
Our Api’s are currently setup to be accessed via access token which the consumers of the Api get by following the Authorization Grant flow.
In the partner redirect scenario we want partner site not go through the Authorization code flow when it makes the Api call because the customer would have already logged into our site to start with using their credentials but instead when we redirect to the partner site provide it securely (SSO payload) the access and refresh token which it can then use to make the Api calls ?.
Is there a grant type that I can invoke telling my authorization provider (PingFederate) that I trust the customer based on the information that he has already provided now give me access token and refresh token and then redirect using that information (None of the grant types that I am aware is able to support it - does Ping OAuth setup support a flow wherein I can say I trust this customer give me access and refresh token )?
It sounds like you'd be combining SAML and OAuth to meet your business need. While it's not defined as a standard grant type, one potential solution is to include an Access Token in the SAML Assertion attribute payload so the partner application can then make calls without going through additional redirects. PingFederate does offer the ability to do this by using OGNL to create an access token in the attribute contract fulfillment. An example of how to do this is in our SDK documentation: https://www.pingidentity.com/content/dam/developer/documentation/pingfederate/server-sdk/9.3/index.html?com/pingidentity/sdk/oauth20/AccessTokenIssuer.html
If you need more guidance on selecting the right OAuth grant type, we have information on our developer portal that covers this. Please refer to: https://www.pingidentity.com/content/developer/en/resources/oauth-2-0-developers-guide.html#get_token