I have an application (ASP.Net Core 2.2, IdentityServer4) which is working fine. Now I need to authenticate some devices or applications in my application to let them call my APIs.
I've read these links:
IdentityServer4 Access Token Lifetime
Bearer token that never expires
but these are not something that I need.
I need to make some kind of authentication that never expires and I just expire that manually. What is the correct solution? Any Ideas would be appreciated.
Perhaps you can use Reference Tokens, not to be mistaken by Refresh Tokens.
From the documentation:
When using reference tokens - IdentityServer will store the contents
of the token in a data store and will only issue a unique identifier
for this token back to the client. The API receiving this reference
must then open a back-channel communication to IdentityServer to
validate the token.
So the reference is only a reference. It contains no information about security or expiration. The referenced information is stored in the data store and is only accessable by the resource that receives the reference token, using back-channel communication. The reference remains valid until it is removed from the data store (token is revoked).
In order to make this work you should use AddIdentityServerAuthentication in the client and api for handling and validating reference tokens. You can configure the client to use reference tokens as follows (as documented):
client.AccessTokenType = AccessTokenType.Reference;
The documentation also mentions a secret for the api.
Related
I'm trying to understand token introspection as I need to implement token introspection for OAuth 2.0. But authentication is so hard to understand... :-( So I've got a couple of questions:
(1) As far as I understand, a post-request (with the access token) is sent to the IP. This then returns whether the access token is valid or not, as well as further information such as the user name.
This looks like the official spec to me: https://www.rfc-editor.org/rfc/rfc7662 it says a post request is needed to validate the access token. Did I understand that correctly
(2) This looks like the corresponding dependency, is it? using using IdentityModel.AspNetCore.OAuth2Introspection
Whats the difference between Microsoft.AspNetCore.Authentication.JwtBearer?
(3) According to the spec only the access token is requied (https://www.rfc-editor.org/rfc/rfc7662#section-2.1)
This example does not pass it but the clientid and the clientsecret:
https://github.com/IdentityModel/IdentityModel.AspNetCore.OAuth2Introspection
services.AddAuthentication(OAuth2IntrospectionDefaults.AuthenticationScheme)
.AddOAuth2Introspection(options =>
{
options.Authority = "https://base_address_of_token_service";
options.ClientId = "client_id_for_introspection_endpoint";
options.ClientSecret = "client_secret_for_introspection_endpoint";
});
Why not?
(4) If I set the config right, .Net Core will do the post-request (for every incoming request to my api) for me automatically, right? (I also added the [Authorize]-Attribute)
(5) How can I get the user context?
(6) I implemented a small example but get a 500. I do not see any error output. How can I log the errors?
The following are some of my understanding and opinions:
(1) The token introspection endpoint needs to be able to return information about a token, so you will most likely build it in the same place that the token endpoint lives. The request will be a POST request containing just a parameter named "token".
(2) JWTs are typically validated locally on the resource server.
It's a technical detail that IdentityServer can also validate JWTs at the introspection endpoint. That could be used e.g. when the resource server does not have an appropriate JWT library (and you don't want to store reference tokens on the IS side).
(3) In my opinion, this appears to be a configuration requesting an access token. Access tokens are the thing that applications use to make API requests on behalf of a user. The access token represents the authorization of a specific application to access specific parts of a user’s data. The Client Credentials grant is used when applications request an access token to access their own resources, not on behalf of a user. Please check this link: Access Tokens.
(4) If you add the [Authorize] attribute to the method that requires authorization, if the configuration is correct, the .Net Core App will automatically request authorization from the authorization server with your information.
(5) Do you want to access end user context on resource server? Maybe this link can help you.
(6) For logging error messages, please refer to this link: How do I log authorization attempts in .net core.
Hope this can help you.
we plan to introduce an API management solution and we're currently setting up a proof of concept with WSO2 AM. We want to use the WSO2 API gateway to check whether a certain consumer application is allowed to use an API and to throttle the request rate.
I work on the identity workflow and I wonder how a consuming application can pass a JWT token to the backend service with WSO2-AM in between.
First, this is our current scenario:
Without API gateway
The consuming application gets a JWT token for its carbon user from an identity provider. The JWT contains some claims about the user, e.g. the roles he/she belongs to.
The app calls the service an passes the JWT token in the Authorization HTTP header like: Authorization: Bearer
The service validates the issuer and signature of the JWT and retrieves the claims from it.
So, this is pretty straight forward. Now we put an API gateway in between the application and the service:
With API gateway
The consuming application gets a JWT token for its carbon user from an identity provider.
The consuming application uses OAuth2 to get an access token for the following API calls. We can use the client_credentials grant type and simply pass the the client id and client secret. I haven't yet tried it, but we could possibly use the JWT grant type (see https://docs.wso2.com/display/ISCONNECTORS/Configuring+JWT+Grant+Type) and use the JWT for passing user information to the API gateway.
The API gateway validates the JWT against the public key of the identity provider when using the JWT grant type.
An access token is returned to the app.
The app sends an API request to the gateway and passes the access token in the Authorization HTTP header.
The gateway validates the access token.
The gateway forwards the API request to the service.
And there is my problem: How can the JWT from 1/2. be passed to the service?
There is a documentation for "Passing Enduser Attributes to the Backend Using JWT" (see https://docs.wso2.com/display/AM210/Passing+Enduser+Attributes+to+the+Backend+Using+JWT), but this would introduce a new JWT, issued and signed by WSO2-AM, and I'm not sure, whether this JWT contains all information from the JWT used to create the access token (or even the original JWT).
Another way I could think of is using a custom HTTP header for passing the JWT through the gateway to the service. I cannot use the Authorization header (as we do without the API gateway), because WSO2-AM expects the access token in that header.
Since I'm not happy with either solutions, I want to ask the experts: How would you solve this?
Thanks,
Torsten
The only possibility I can think of is to send the JWT token in a custom Header for the backend service.
We consider using OpenID Connect with ID tokens for authentication of our public API.
These are the usage scenarios we'd like to cover:
Web UI (single page, client-side JavaScript app)
Command line interface (CLI) used in an interactive session
CLI used non-interactively, e. g. in a CI/CD pipeline
Other API calls executed in a non-interactive session
The idea for (1) and (2) is to use the OIDC implicit grant type, so that the user authenticates interactively (username/password) at our OpenID Connect identity provider and permits the RP (relying party, client) to access the users identity. The identity provider will then issue a short-lived ID token, a refresh token and (optionally?) an access token to the RP.
For (3) and (4) an interactive authentication is out of the question. We'd instead like to issue tokens to the users which allow them to access our API on their behalf. These tokens should be long living, only invalidated when they get deleted in the system.
Still, we want to use JWT just like the ID tokens issued by the identity provider as a carrier of identity information for all API requests internally.
My questions are:
Can this be done purely with one of the tokens issued by the OpenID Connect implicit grant type?
Can an access token be issued in a long-lived (no expiry, only invalidated by deleting from the system) way and then be exchanged by the client against an ID token?
Or is the refresh token the thing to use for exactly that?
Or do we have to solve this outside OpenID Connect? Which leaves the question how to resolve opaque tokens from API requests against identity details (JWT) for use in our API/services?
If you use implicit flow (for Scenarios 1 and 2), you can't use refresh tokens. You need client credentials (client ID and secret) to request for refresh tokens. In the Implicit flow, we don't store any client credentials.
When a client is Public client (SPA,etc..), it is not safe to store client secret in it. So public clients generally use Implicit flow. Implicit flow doesn't support refresh tokens. Some of the OIDC libraries implement Silent token renewal/refresh feature to circumvent the absence of refresh tokens. But there are some limitations with that model (you need to have active session with IDP to get the renewal working without any interruption)
TL;DR -> If a client is public client, use implicit flow (which don't need client secret to get access tokens from IDP). Implicit flow doesn't support refresh tokens.
Can this be done purely with one of the tokens issued by the OpenID Connect implicit grant type?
It is not possible to use refresh tokens with implicit flow. Authorization code flow supports refresh tokens but can't be used with SPA clients. So you need a combination of OAuth 2.0/OIDC flows.
Can an access token be issued in a long-lived (no expiry, only invalidated by deleting from the system) way and then be exchanged by the client against an ID token?
These are two different things:
"Invalidated by deleting from the system" : With this we are discussing about Self-Contained tokens vs Reference tokens.
Self-Contained Tokens: These tokens contains all the information required to validate its authenticity in it - for e.g. the issuer details, its validity, etc.. A client don't need to make a back-channel call to STS to confirm the authenticity. These tokens are sometimes hard to revoke and will be valid for the duration as specified in the token.
Reference Tokens: Reference tokens are generally opaque tokens which contains a GUID like identifier in it and no other details. In order to validate the authenticity of these tokens, the client needs to make a back-channel call to STS. One main advantage is it can be easily revoked by deleting the corresponding identifier in STS DB.
"exchanged by the client against an ID token Refresh token" - I am assuming you are referring to Refresh tokens instead of ID token. We use Refresh token for this purpose
Or is the refresh token the thing to use for exactly that?
Yes. Refer to the above comments
Or do we have to solve this outside OpenID Connect? Which leaves the question how to resolve opaque tokens from API requests against identity details (JWT) for use in our API/services?
If you use opaque tokens, OIDC/OAuth 2.0 has several endpoint (like UserInfo) to get further information about the user. You can also use Introspection endpoint to know the validity of the token.
(Scenarios 3 and 4): I am not sure how you plan to use this - But for any non-interactive client(which is acting on its own and not behalf of user), you should use client credentials flow.
If the client want to act on behalf of user, you should enable a way for the user to approve this behavior.
I recommend anyone who is interested in OpenID Connect (OIDC) to look into OAuth2 specification. Since OIDC is built up-on OAuth2, it inherits many fundamental features.
First thing to note is Implicit flow does not return a refresh token.
The implicit grant type is used to obtain access tokens (it does not
support the issuance of refresh tokens) and is optimized for public clients known to operate a particular redirection URI
If you want to rely on refresh tokens, then you MUST consider this fact.
Can this be done purely with one of the tokens issued by the OpenID Connect implicit grant type?
It depends on the design and exact requirements. But you can indeed build the authentication on top of Id token and use access token for API calls. To validate access tokens, you can use introspection endpoint from API endpoint.
Can an access token be issued in a long-lived (no expiry, only invalidated by deleting from the system) way and then be exchanged by the client against an ID token?
This could be possible depending on the configurations of identity provider expose. But by specification, this should not be done for a client who use implicit flow. And simply because of security reasons. This is the very same reason why implicit flow does not return a refresh token. On the other hand, refresh tokens are the one which can live longer. For example, Google's refresh tokens never expires (reference - 8953983).
Or is the refresh token the thing to use for exactly that?
As mentioned previously, refresh tokens can long-lived. And it can be exchanged for a fresh access token. Returning of the id token for a refresh token will depend on identity provider implementation. For example, Azure AD do return an ID token for refresh token response. But going beyond that, the identity provider can offer a user info endpoint. A good article can be found from this link
Or do we have to solve this outside OpenID Connect? Which leaves the question how to resolve opaque tokens from API requests against identity details (JWT) for use in our API/services?
ID token indeed help to authenticate the end user from client side. But when it comes to validate user from API endpoint, you can think about using introspection endpoint or a user info endpoint. But be mindful, some identity providers do not provider introspection endpoint. At the time of writing this article Azure AD do not expose one (reference - 43378748) but do provide a user info endpoint.
I have an API Server (Resource server) and multiple apps, Web GUI (SPA) and a Desktop client and maybe more coming.
I'd like to use openid-connect besides http basic authentication for my API Server.
It should be configurable which openid provider to use. My own, facebook, google...
I only want to do authentication, I do not need their API. I only need some profile data like email or firstname.
Let's say I have configured google as my IdP and I'm currently using my Web GUI (SPA). I need to login, no problem, according to https://developers.google.com/identity/protocols/OpenIDConnect I redirect the user to google, get my authorization code and the Web Gui (SPA) gets an id_token and access_token from google.
No problem so far, but now the SPA has to work with my API Server and the API Server needs to authenticate every request (since it is a stateless rest api) coming from the Client (WebGui SPA) and needs to know which user actually did this.
A
So the access_token from google is meant to be used to access google api's right? But I also could just pass this access_token with every request to my api server and the api server calls https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=xxx to verify the access_token and get the account name (mail). But this doesn't sound right, does it?
B
I also have and id_token which I can verify without calling google server everytime. So could I also just pass the id_token as bearer with every request to my api server and the api server can verify the id_token? But according to openid-connect spec the access_token is actually the one which just get passed to the api server and the id_token must stay on the client.
But then the id_token would be completely useless to me, the API server needs to know who the user is, the client (Web GUI) doesn't really care.
C
Or since it is my own API Server, does my API Server actually needs to implement the whole oauth2 system by itself, just not authentication but creating access_token and more. So I would have a /api/tokensign to which I can pass the id_token from google, the API verifies the id_token and creates an access_token for my WebGUI (SPA). And this new access_token can be passed as bearer to every api request. This actually sounds as the best solution according to specs, but do I really need to implement oauth2 by myself into my API? Sounds like a heavy addition since A and B could also be implemented.
My rest-api needs authentication with every request so is A, B, C the right approach? Please don't tell me this is opinion based, it is not.
What is the right way using oauth2/openid-connect for authentication?
You can use all three methods you have mentioned above, but indeed with some considerations. I will explain them with regards to available specifications.
Scenario - Two systems S1, S2
S1 - Identity provider
S2 - API endpoint
What you need - Trust and use 'Tokens' issued by S1 to access S2
Explanations for proposed solutioins A, B and C
A - Verify tokens issued by S1 for each call
This can be done using the RFC7662 - OAuth 2.0 Token Introspection endpoint. This validation is valid by the specification so yes you can use the token verification endpoint.
Advantage for this method is that, if a token is revoked, the effect is instantaneous. The very next API call will fail. But indeed there's the implication on performance. You need an extra verification service call.
Note that you do not need to get the account name from this verification response. It could be taken from ID token and could be used to verify for extra protection.
B - Trust tokens issued by S1 for each call
Now this approach is something extended from RFC6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage. You can indeed use ID toke to authenticate and authorise an end user. This link contains a good explanation on the ID token usage as a bearer token.
You can indeed verify the validity of token using MAC and even encryption. But be mindful to use short lived tokens and to always use TLS. And be mindful about refreshing tokens.! Because according to openID connect specification, ID token is not a mandatory item for a refresh token request.
C - A wrapper for federation
For this you can write your own solution or use an existing solutions (ex:- WSO2 identity server). This identity server will configured to choose the identity provider on your application (client like desktop app or web app). Identity server will do the necessary redirects and provide you the required tokens. But indeed you will need to use introspection endpoint to validate the token validity.
If you go one step ahead of this solution, you can try to implement a code exchange mechanism. You can exchange the token carry from external to tokens issued internally by one of your system (ex:- Google access token to your internal access token). The advantage of this approach is you have control over validation. Also since subsequent token validations are done internally, there should be a performance improvement.
Hope this explains some doubts you have.
Is there an example of an OAuth implementation or profile which uses multiple authorization tokens in one interaction? Can this be done with vanilla OAuth (as opposed to an extension)? Is there any discussion on the reasons for or against using multiple tokens in one request?
OAuth WRAP uses two tokens, but only one is an authorization token; the other is a request token which is used to obtain a new authorization token. What is the reasoning behind this? Does this bake sessioning into a single authorization token simply to make token passing more straightforward? Does anyone recommend building OAuth authorization tokens in this way across multiple interactions?
A "protected resource request" (i.e. a request to retrieve some resource which requires you to authenticate using OAuth) in standard OAuth carries only one OAuth token. The consumer key is also sent. The secrets corresponding to each of these tokens are used together to generate the signature.
WRAP also has the concept of an access token but it introduces the concept of a refresh token which is not included in a protected resource request but is instead sent in a direct request from client to service provider when the client's access token has expired and it needs to obtain a new one.
WRAP tokens, unlike OAuth tokens, do not have an associated secret but is instead used more like a temporary session identifier. Since this token may be exposed in a browser cookie or other browser state, WRAP allows for that token to be short-lived, allowing it to be discarded when the user signs out or after some short period of inactivity. The refresh token is known only to the client and service provider and is thus longer-lived.
A refresh token is not necessary in OAuth because the Token Secret serves as the secret known only to the client and service provider.
Both protocols have two values for the client to keep track of, one of which is more private than the other, but WRAP uses the more private token in a different way such that implementers do not need to generate and verify signatures.