I would like some clarification on how to use ID tokens and access tokens in an implicit grant flow.
I have an Angular SPA using MSAL.js for Angular package and a Web API. The API does NOT call any external services, like MSFT Graph. The back end uses role claims from JWT to establish RBAC authorization to our API functionality only.
This doc says:
https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens
id_tokens are sent to the client application as part of an OpenID Connect flow. They can be sent along side or instead of an access token, and are used by the client to authenticate the user.
ID Tokens should be used to validate that a user is who they claim to be and get additional useful information about them - it shouldn't be used for authorization in place of an access token.
This doc shows an authentication flow where a web API is called with an ID token instead of an access token:
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow
This sample code sends ID token too (calling own Web API sample):
https://github.com/Azure-Samples/active-directory-javascript-singlepageapp-dotnet-webapi-v2
The sample back end validates ID token audience against Client ID of the app that issued it.
Given our API is the only consumer of tokens, should we use ID tokens or access tokens?
Generally speaking, when securing your API with the Microsoft Identity platform, clients should be using the access token when making API requests, not the ID token.
check this part
It first calls acquireTokenSlient, which gets a token from the cache if available if not
it calls acquireTokenPopUp which will get an acces token for the specific scope, I am not sure if it would open up a popup window or will get a token in the background with hidden iframe. But it would fetch an access token for sure. API can never be accessed with ID token.
check https://learn.microsoft.com/bs-latn-ba/azure/active-directory/develop/scenario-spa-acquire-token for more clarification
When I authenticate my single page app to my SFDC org using user-agent flow I am getting an access token and an openID token.
I need to use one of them (not sure which) to authenticate and get access to another system (Again, via API).
My understanding that I need to use the OpenID token in this case, as the other system will have no idea how to validate the access token. While the Open ID token signature can be validated using the same certificate used to sign it (the one in my SFDC org) and the user can be authenticated based on that. Something doesn't sound to be right, can anyone help explaining how I can use one token received from one system (and IDP) to access another system
This is a common problem faced with token usage. Here is a link for a similar question with Google oAuth
In short, id token is intended for the client. Client consumes the id token and and authenticate the end user by validating it. On the other hand, access token is to grant authorisation. It allows client to access protected resources, representing the end user. In this manner, answer to your question is to use access token.
To validate an access token and obtain end user details, you can use use userinfo endpoint. SalesForce expose this endpoinr through url,
https://login.salesforce.com/services/oauth2/userinfo
This endpoint consumes access tokens, validate them. If valid, it return information about end user to which the access token was issued. This way you validate access token and receive. Read more from this article
Does not having a secret defined for an IdentityServer4 API Resource introduce a security vulnerability?
I'm a little confused on the Introspection Endpoint, when it is used, and whether or not someone could use the Introspection endpoint to bypass Authorization and access an API without a defined secret (by a POST with just the API name as a parameter).
Is this possible? Or is the introspection endpoint only authorized through defined clients that use something like the Client Credential Grant?
The introspection endpoint will only validate a posted token, it shouldn't accept an API name in its request.
It can be used to validate reference tokens (or JWTs if the consumer does not have support for appropriate JWT or cryptographic libraries). The introspection endpoint requires authentication using a scope secret.
http://docs.identityserver.io/en/release/endpoints/introspection.html
This shouldn't be an endpoint you need to implement, it is included by identity server in the same way as the '.well-known/openid-configuration'.
A use case for this endpoint would be an API being passed a token and wanting to confirm its genuine and still valid (not expired or revoked), the response would include the claims associated with the token (users claims with the tokens scope taken into consideration)
For introspection security considerations see the RFC 7662 Section 4
An API Resource requires a Client Secret when you are using the Authorization Code Flow as its sending claims on the back channel.
If you are using Reference tokens you will also require a Client Secret, as the access token is never presented to the client, but instead the reference token is passed from the client to the api resource, and then onto the identity server in exchange for the access token.
It really depends on the client and the flow.
I am using token based security in my web app. The server side is wrote using c# and i am using openiddict for logging in and issuing tokens, found here. I am currencyly using Implict flow.
By default my tokens have a lifespan of 1 hour, after that you have to logging again. I have locked down my API to accept bearer tokens only and not cookies.
I wanted to implement refresh tokens but after reading many websites, it appears that implementing refresh tokens on a web app, is not a good way to go due to a hacker getting the refresh token. I know that to use refresh tokens, you must use code flow, instead of implict, which i can do.
How do people get round this situation in their web apps? I cant be the only one who wants a token to last longer than an hour in a web app?
The approach recommended by OpenID Connect is to send an authorization request in a hidden frame with the same parameters as the ones you use for the initial implicit flow request plus prompt=none and optionally, an id_token_hint corresponding to the id_token you extracted from the authorization response.
When using prompt=none, the identity provider won't display any consent form and will directly redirect the user agent to the redirect_uri you specify, with the new token appended to the URI fragment, just like for a classic implicit flow request. You can retrieve it by extracting it from the popup.location.hash property.
If the request cannot be processed (invalid request, unauthenticated user, invalid id_token_hint, consent required, etc.), an error is returned and the identity provider either redirects the user agent to the redirect_uri with an error parameter or stops processing the request.
Note that due to the same origin policy, you can't access popup.location.hash if the current location belongs to a different domain (e.g if the identity provider refuses to redirect the user agent to your client app): it will throw an access denied exception. In this case, it's always better to add a timeout to your "refresh" operation.
Sadly, there are very few libraries that can help you with this task. oidc-token-manager is one of them, but it has a few limitations that will prevent it from working OTB with OpenIddict: it doesn't support raw RSA keys (you have to explicitly use a X509 certificate in the OpenIddict options) and it doesn't send the id_token_hint parameter required by OpenIddict when sending a prompt=none request.
I want to build small application. There will be some users. I don't want to make my own user system. I want to integrate my application with oauth/oauth2.0.
There is no problem in integration of my front-end application and oauth 2.0. There are so many helpful articles, how to do this, even on stackoverflow.com. For example this post is very helpful.
But. What should I do after successful authorization on front-end? Of course, I can just have flag on client, which says "okay, mate, user is authenticated", but how I should interact with my backend now? I can not just make some requests. Back-end - some application, which provides API functions. EVERYONE can access this api.
So, I need some auth system anyway between my FE and BE. How this system should work?
ps I have some problems with English and may be I can not just correctly 'ask google' about it. Can you provide correct question, please :) or at least give some articles about my question.
UPD
I am looking for concept. I don't want to find some solution for my current problem. I don't think it is matters which FE and BE I use (anyway I will
provide information about it below)
FE and BE will use JSON for communication. FE will make requests, BE will send JSON responses. My application will have this structure (probably):
Frontend - probably AngularJS
Backend - probably Laravel (laravel will implement logic, also there is database in structure)
Maybe "service provider" like google.com, vk.com, twitter.com etc remembers state of user? And after successful auth on FE, I can just ask about user state from BE?
We have 3 main security concerns when creating an API.
Authentication: An identify provider like Google is only a partial solution. Because you don't want to prompt the user to login / confirm their identity for each API request, you must implement authentication for subsequent requests yourself. You must store, accessible to backend:
A user's ID. (taken from the identity provider, for example: email)
A user token. (A temporary token that you generate, and can verify from the API code)
Authorization: Your backend must implement rules based on the user ID (that's your own business).
Transport security: HTTPS and expiring cookies are secure and not replayable by others. (HTTPS is encrypting traffic, so defeats man-in-the-middle attacks, and expiring cookies defeats replay attacks later in time)
So your API / backend has a lookup table of emails to random strings. Now, you don't have to expose the user's ID. The token is meaningless and temporary.
Here's how the flow works, in this system:
User-Agent IdentityProvider (Google/Twitter) Front-End Back-End
|-----------------"https://your.app.com"---------->|
|---cookies-->|
your backend knows the user or not.
if backend recognizes cookie,
user is authenticated and can use your API
ELSE:
if the user is unknown:
|<--"unknown"-|
|<----"your/login.js"----------+
"Do you Authorize this app?"
|<------------------+
|--------"yes"----->|
+----------auth token--------->|
|<---------/your/moreinfo.js---|
|-------access_token ---------->|
1. verify access token
2. save new user info, or update existing user
3. generate expiring, random string as your own API token
+----------->|
|<-------------- set cookie: your API token --------------------|
NOW, the user can directly use your API:
|--------------- some API request, with cookie ---------------->|
|<-------------- some reply, depends on your logic, rules ------|
EDIT
Based on discussion - adding that the backend can authenticate a user by verifying the access token with the identity provider:
For example, Google exposes this endpoint to check a token XYZ123:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
I read through all the answers very carefully, and more than half the people who responded are missing the question completely. OP is asking for the INITIAL connection between FE & BE, after the OAuth token has been issued by the Service Provider.
How does your backend know that the OAuth token is valid? Well keep in mind that your BE can send a request to the Service Provider & confirm the validity of the OAuth token, which was first received by your FE. This OAuth key can be decrypted by the Service Provider only because only they have the secret key. Once they decrypt the key, they usually will respond with information such as username, email and such.
In summary:
Your FE receives OAuth token from Service Provider after user gives authorization. FE passes OAuth token to BE. BE sends OAuth token to Service Provider to validate the OAuth token. Service Provider responds to BE with username/email information. You can then use the username/email to create an account.
Then after your BE creates the account, your BE should generate its own implementation of an OAuth token. Then you send your FE this OAuth token, and on every request, your FE would send this token in the header to your BE. Since only your BE has the secret key to validate this token, your application will be very safe. You could even refresh your BE's OAuth token on every request, giving your FE a new key each time. In case someone steals the OAuth token from your FE, that token would be quickly invalidated, since your BE would have already created a new OAuth token for your FE.
There's more info on how your BE can validate the OAuth token. How to validate an OAuth 2.0 access token for a resource server?
let's use OAuth concept to begin,FE here is Client , BE here is Resource Server.
Since your client already authorized, Authorization server should grant
Access token to the client.
Client make request to the resource server with the Access token
Resource server validate the Access token, if valid, handle the request.
You may ask, what is the Access token, Access token was issued by authorization server, grant to client, and recognized by resource server.
Access token is a string indicate the authorization information(e.g. user info, permission scope, expires time...).
Access token may encrypted for security, and you should make sure resource server can decrypt it.
for more details, please read OAuth2.0 specification https://www.rfc-editor.org/rfc/rfc6749.
Well you don'y need User-System on your Front End side.
The front end is just a way to interact with your server and ask for token by valid user and password.
Your server supposed to manage users and the permissions.
User login scenario
User asking for token by entering his username and password.
The server-API accept the request because it's anonymous method (everyone can call this method without care if he's logged in or not.
The server check the DB (Or some storage) and compare the user details to the details he has.
In case that the details matches, the server will return token to the user.
From now, the user should set this token with any request so the server will recognize the user.
The token actually hold the user roles, timestamp, etc...
When the user request for data by API, it fetch the user token from the header, and check if the user is allowed to access that method.
That's how it works in generally.
I based on .NET in my answer. But the most of the BE libaries works like that.
As am doing a project for SSO and based on my understanding to your question, I can suggest that you create an end-point in your back-end to generate sessions, once the client -frontend- has successfully been authorized by the account owner, and got the user information from the provider, you post that information to the back-end endpoint, the back-end endpoint generates a session and stores that information, and send back the session ID -frequently named jSessionId- with a cookie back to the client -frontend- so the browser can save it for you and every request after that to the back-end considered an authenticated user.
to logout, simply create another endpoint in the back-end to accepts a session ID so the back-end can remove it.
I hope this be helpful for you.
You need to store the token in the state of your app and then pass it to the backend with each request. Passing to backend can be done in headers, cookies or as params - depends on how backend is implemented.
Follow the code to see a good example of all the pieces in action (not my code)
This example sets the Authorization: Bearer TOKEN header
https://github.com/cornflourblue/angular-registration-login-example