In OAuth 2 why is there need for an Access Token when there is the Authorization Code? - api

In OAuth 2 the client app exchanges an authorization code for an access token. And with the access token, the app can make API calls. However, I don't really get why OAuth 2 has this step; it seems like an extra step.
One reason I can think of is that the authorization code is given through a redirect call on the client side, so it has the potential to be compromised, thus it's short lived; whereas the access token is given server-to-server.
That is true, but there is also the secret API key that the app sends. Then why couldn't same be done with the authorization code?
Say there was no access token but just the authorization code. Then even if someone gets the authorization code, they wouldn't be able to do anything if the OAuth server also checked the secret key along with the authorization code.
It should allow the OAuth server to:
Make sure the request was made by the correct app (authenticate)
Determine what types of permission were granted (authorize)

Ability to get access_token directly (Implicit grant type) is required in the cases of JavaScript clients or web applications running in a browser. Because, these clients are not secure based on the options available for saving the client secret. The client id and secret are required to exchange authorization code for an access_token.
These two grant types exist to provide various levels of security when implementing authentication.
If the resource served by the API is extremely sensitive then you want at most security, which is provided by Authorization Code flow. In this grant type you validate the client (server side API or a mobile client) and the resource owner (user) before granting access to the resource. The access_token is not even exposed to the browser/ user (since a stolen token can give access to the resource), thus giving high degree of security. This flow is complex and involves more round trips to the authorization server, but, provides more security.
If you don't need that kind of security on a resource you can use Implicit grant type where the browser/ user has access to the token. This flow is simple with only one trip to authorization server. It will not validate the client. No need to save the client secret with the browser.
Hopefully this makes sense. Please let me know if you have any questions.
Thank you,
Soma.

Related

identityserver4 protect public api

I am using identity server 4, I followed the tutorial, so I have an api, mvc client, console client, and js client.
I saw this blog too, which is probably close to what I need:
https://medium.com/all-technology-feeds/testing-your-asp-net-core-webapi-secured-with-identityserver4-in-postman-97eee976aa16
what I need is an api, where clients can access data, but first, they need authenticate.
we also have the console client, which is also close to what I need.
The only issue with this examples is that in both cases client knows the secret. But in our case multiple clients should use the same api, and if they all have the same secret, they can log in on behalf of each other, but I don't want to have different secrets.
So what I think I could do is to create an api which takes username and password, and returns the token. But I am not sure if this is the right way to do things? This feels like a resource owner flow, which is not supposed to be used for client facing APIs if I am correct. But in that case, how should I go it?
thanks
It seems that there is some confusion. Allow me to give a short summary. First the terminology:
A user is a human that is using a registered client to access resources.
A client is a piece of software that requests tokens from IdentityServer - either for authenticating a user (requesting an identity token) or for accessing a resource (requesting an access token). A client must be first registered with IdentityServer before it can request tokens.
Resources are something you want to protect with IdentityServer - either identity data of your users, or APIs.
Client credentials: The simplest grant type and is used for server to server communication - tokens are always requested on behalf of a client, not a user.
Now about authentication. The client requests tokens at the IdentityServer endpoint. When you use a client in combination with the client credentials flow, then you'll need a clientid + secret. Where secret is really secret and should be known to the client only. You can't use the same secret here. Seems logical when compared to users, they don't share the same password either.
This is close to the resource owner flow, however a client cannot login as a user. For that you'll need another flow, like the hybrid flow. In that case the client logs in on behalf of the user. The difference is the presence of the "sub" claim (the id of the user) in the token.
The client in this case is your app: console or mvc. The first only supports client credentials where the secret is mandatory, the second supports a hybrid flow, where secret may be omitted:
In certain situations, clients need to authenticate with
identityserver, e.g.
confidential applications (aka clients) requesting tokens at the token endpoint
APIs validating reference tokens at the introspection endpoint
The Api is your resource, that you want to protect. The Api never authenticates a user or client. This is done by IdentityServer. It only verifies the token (using the IdentityServer4.AccessTokenValidation package). For that it has its own secret that should only be known to the Api.
In order to grant the client access to the resource you'll need to add the scope to the client in the configuration of IdentityServer. The client is then allowed, not required, to request a token that grants access to the resource.
Again, the Api has nothing to do with authentication. It is also not bound to one client. Multiple clients can access the resource. All you have to do is add the scope to each client that should have access to the resource.
So there is really nothing against it that clients and resources know their secret. You don't have to change anything. All you have to do is choose the appropriate flow.

How to authenticate SPA users using oAuth2?

Alright, I've spent several days looking for a proper solution on how to properly authenticate users when working with SPAs.
I have my own website.
I have my own API.
I have my own Single Page Application.
I have my own database of users.
The Goal: I need to get an access_token by providing a username and a password.
I looked at OAuth2 Implicit Grant, but it requires users to Approve/Decline the app after successful authentication. It doesn't work in my case since I own both the app and the API.
I looked at OAuth2 Password Grant, which is not perfect since I need to expose client_id/client_secret.
The reason I'm looking at OAuth2 is because the API will eventually be public.
Is there a standard way of doing this? My current options:
Forget about OAuth2 and manually generate access_token when user POSTs username/password (in this case I'd have to introduce OAuth2 when API goes public)
Use OAuth2 Password Grant and inject client_id/client_secret on the server, so just to keep client app very simple (also avoid all of those dev/staging/prod client_id/client_secret pairs)
Implicit Grant
You are right that Implicit grant type does not look appropriate. But I think your reason for not favoring it is incorrect because the approval step is not mandatory and in Spring OAuth 2 implementation (I don't know which implementation you are using) you can configure the Authorization server to auto approve authorization requests so that the approval step is skipped.
The reasons I think the "Implicit flow" is not suitable are
​The client authentication step by providing client secret and authorization code is missing. So less security.
The access token is sent back as a URL fragment (so that the token doesn't go to the server) which will continue to stay in browser history
If XSS attack occurs, the malicious script can very well send the token to the remote server
Resource Owner Password Credentials Grant
If the authorization server and the resource server are the same, I think this is a quick way of getting up and running. RFC 6749 in Section 4.3.2 says:
If the client type is confidential or the client was issued client credentials (or assigned other authentication requirements), the client MUST authenticate with the authorization server as described in Section 3.2.1.
This means that the client authentication with client secret is not mandatory here. Now, for authorization code grant type, we need the client secret because the user provides his/her credentials directly to the authorization server and then when the client requests for the access token, it doesn;t have anything else other than the client secret to prove to the authorization server that this is a genuine request.
But in case of resource owner password credential grant type, the user has provided its credentials to the client itself and the client will then send these same user credentials for requesting access token. Therefore, the access-token request can be authenticated with the user credentials only and if we don't provide a client secret here, I don't think we are losing anything in terms of security.
So, you can definitely use password credential grant type in your SPA.
Authorization Code Grant
I think this should be the preferred option provided the client secret is not stored in the browser. After user authentication (and optionally user approval), the authorization server can redirect the browser to a server side endpoint with the authorization code in the URL. The server side end point will the request for the access token using the authorization code, client id and client secret (which is stored in the server side only). Once the access token is available, the server side endpoint can redirect (HTTP response code 302) the user to the SPA URL with appropriate cookies for CSRF protection and access token. Thus we are not storing the client secret in the browser.
By using authorization code grant type, you are basically making the solution more secured and generic. In future, if you want to do a single sign-on with a different SPA, you can do that easily by reusing the same authorization server with its integration with the authentication database (preferably an LDAP server).
For further details, refer to my StackOverflow answer here.
Building off what has been said already, I would recommend the 'Authorization Code Grant' but with the addition of the PKCE (Proof Key for Code Exchange / 'pixie') extension - for added security, regardless of whether you're implementing a 'public' or 'confidential' type client.
With PKCE, you don't need a client-secret for public clients (/it's kind of like generating a temporary client-secret at the very outset/beginning of each authentication attempt/instance - although even with PKCE for confidential clients you should ideally still use a client secret).

How to verify which resources each user can access with OAuth and OpenID Connect?

Suppose we have some RESTful API whose resources we want to expose. End users will work with this API through client applications like mobile apps and Javascript based clients that run on web browsers.
With OAuth 2.0 this RESTful API will lie on the Resource Server and we will have one Authorization Server on which the client applications are registered. The users will then be registered at the authorization server and will be able to grant permission to those applications access resources on their behalf or not.
So when the user access one client application he will be redirected to the Authorization Server and be prompted to grant permissions to said client app. After that an access token is issued and the client is able to make requests to the Resource Server.
All of this is quite clear to me. There's just one missing piece: the protection of each resource might be user-dependent. To be more precise it might be claims-dependent. What I mean by that is we can have the following situation:
The resource http://resourceserver.com/api/first-resource should only be accessible to users with claim "ExampleClaim" with value 123.
The resource http://resourceserver.com/api/second-resource should only be accessible to users with claim "AnotherClaim" with value 123.
The resource http://resourceserver.com/api/third-resource should be accessible to any users.
When I first heard of OAuth was dealing with ASP.NET WebAPI and I dealt with that in the following way: when the request was sent with the Authorization: Bearer [token] header, on server side the thread principal was set and I thought that this meant the user was authenticated with the API. So I used [Authorize] attributes in order to verify if the user could access the resource.
After studying OAuth more deeply I saw this was a terrible misuse of the protocol. As I've learned, OAuth authorizes applications and not users. When the request is made with the Authorization header, as I've learned, the access token shouldn't contain information about the user, just about the application being allowed to make the request.
Considering that, sending the Authorization header with the request doesn't identify the user and does don't say if the user can or cannot access said resource.
In that case, how does one perform this kind of authorization? I mean, not authorization of the client app performing the request, but the authorization of the user accessing the resource based on his claims? I believe this is where OpenID Connect and it's ID tokens come in, but I'm unsure. How does one manage this?
An access token does not contain a user's claims, but it contains the subject of the user who has granted permissions to the client application. "Subject" is a technical term and it means a unique identifier. Simply saying, "subject" is a user ID in your database.
At a protected resource endpoint, you will do:
Extract an access token from the request. (RFC 6750)
Get detailed information about the access token from the authorization server. (RFC 7662)
Validate the access token. The validation includes (a) whether the access token has expired or not, and (b) whether the access token covers scopes (permissions) that are required by the protected resource endpoint.
The steps above from 1 to 3 are an access control against client applications. OAuth 2.0 (RFC 6749) is for this. See "Protected Resource" by Authlete (by me) for details about these steps.
After the steps above, then you will do:
Extract the subject from the access token. Again, "subject" is a unique identifier of the user.
Retrieve claims of the user from your database.
Validate the claims as you like.
The steps above from 4 to 6 are an access control against users. OAuth 2.0 is NOT for this.
The primary purpose of OpenID Connect is to get an ID token in a verifiable manner. You can confirm that an ID token has been issued by the right party by verifying the signature attached to the ID token. See JSON Web Signature (JWS) (RFC 7515) for details about signature.
An ID token itself is not a technology to protect Web APIs. But you may be able to use it for that purpose if you use at_hash claim in an ID token properly (see "3.1.3.6. ID Token" in OpenID Connect Core 1.0). However, at a protected resource endpoint, it will be much easier to get claims directly from your database than to parse an ID token.
**[ Additional answer #1 for the comment ]**
In your use case, you don't need ID tokens. It's because an access token already contains information about the subject of the user. In normal cases, the information is equivalent to the value of sub claim in an ID token.
Therefore, you don't need an ID token to get the subject of the user. See the description of step 4, and you can find "extract the subject from the access token."
**[ Additional answer #2 for the comment ]**
So is there anything wrong in extracting the subject from the access token like that and verify the claims? Or this is the right way of doing things?
There is nothing wrong. For example, suppose you define a Web API, https://api.example.com/profile, which returns the profile information of a user. In normal cases, such an API would accept an access token and then extract the subject from the access token to determine which user to refer to. On the other hand, if the API did not extract the subject from the access token, it would have to require "subject" as a request parameter to determine which user to refer to (or require an ID token that contains "sub" claim). Even in such a case, the API must check whether the subject specified by the request parameter and the subject associated with the access token are identical because otherwise, it would become a security issue.
Checking claims after extracting the subject is also a normal step. For example, you may want to restrict the functionalities of your service based on the plan that the user has paid for (Free plan, Lite plan, Enterprise plan, or whatever). In this case, you would have to refer to plan claim. Of course, checking such a claim can be done only after extracting the subject from the access token.
Therefore, (1) extracting the subject from an access token and then (2) verifying the claims of the user are normal and even typical steps in implementations of protected resource endpoints.
You are right, OAuth is NOT an authentication protocol but rather a delegation protocol.
OpenID Connect adds two notable identity constructs to OAuth 2.0's token issuance model.
an Identity Token - the delivery of which from one party to another
can enable a Federated Identity SSO user experience
a standardized identity attribute API - at which a client can
retrieve desired identity attributes for a given user.
The ID TOken can be presented to the userinfo_endpoint to obtain the information and provides level of assurance that the user has been authenticated by the OpenID Provider.
BTW: The "sub" ie only unique within the context of the Authorization Server. It is recommended IF you store the sub you also store something like iss-sub. The thoughts are tsmith at Google may not be tsmith at Twitter

Architecturing API keys and access tokens

I have a question regarding how I should architecture a REST API using access token and API keys.
I have an API that needs authentication. I want to enable two use cases:
The user logs into the interface using OAuth2 (password grant), and is granted a temporary access token. This token is used to authenticate the user. Therefore, the UI, that itself using the API, can fetch data and display it.
I also want the user to have an API key to do the same calls, but in its application. Obviously, contrary to the access token, I want the API key to be long lived. Also, contrary to the access token that is tied to a given user (if we introduce a team mechanism, each user will have different access token, although they access the same resources), the API key should be unique to the project.
While similar, I'm not sure about how should I architecture that. I think that, internally, both API keys and access tokens should be stored in the same table, but API keys having no expiration time. Am I right?
One thing I'm not sure also is the concept of client. It seems that in the spec, the client is more like an external application. However may I actually use this concept here?
For instance, each "project" is actually a different client (although the client here is the same application, not an application created by a third-party developer).
Therefore, if user A creates an account on the system, a client A will be automatically created, with an access token tied to the client A, with a long-lived access token (aka API key). This can be used to perform API calls directly on his code, for instance.
Then, if user A logs into the dashboard, a temporary access token will be created, but this time with no application, but tied to the user, with a short life.
Does this sound sane? Have anyone already implemented such a thing?
Thanks!
I think you should not consider the "API keys" a substitute of the access token.
You will have to use an access token anyway to bear the authentication between requests, so what you're actually modelling with your "API keys" is not a replacement of the usual bearer token, but rather a different client that provides other grant types to request a token with.
The flow I'd personally implement is the following:
The user authenticates with the password grant type with a common client for every user (i.e. your "web app" client, which is public, i.e. it doesn't have a client_secret).
The user can then create its own client. As per OAuth2 specs, these are not public, so they will consists of a client_id and a client_secret. These are what you call "API keys".
A user will then be able to request an access token via their client, with any given grant type you want to support (e.g. direct client credentials, authorization code, implicit, third parties, etc.). You will have to stress quite a bit about the due safety practices on how to handle the client credentials.
Obviously, you will have to implement your OAuth2 server in such a way that clients can belong specific users, and have different acceptable grant types (i.e. you may not want to allow the password grant usage with a user client, while you may want to disallow any grant type other than the password one for your web app client).
You will then be able to define tokens TTLs, or lack thereof, on a per client or per grant type basis (e.g. access token requested via password grant, only usable by web app client, will have a short TTL, while authorization code grant will provide long lived tokens).
I would advise against complete lack of TTL, though, and rather use the refresh_token grant type to renew expired access tokens.
Furthermore, you'll probably have to define an authorization system of some some sort (ACL, RBAC, whatever), to define which client can do what. This means each access token should contain a reference to the client used for its creation.
So, to sum it up, here are the relations:
User has a Client.
Client has a User.
Client has many Token.
Token has a Client.
Token has a User.
YMMV on bidirectionals.
You should be able to implement everything I described with the most common OAuth2 servers implementations of any given platform.
TL;DR: "API keys" are actually OAuth2 clients.
I wrote a post about the way to use access tokens for RESTful applications: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/. Perhaps can this give some hints.
To answer your questions, I think that we need to have something homogeneous. I mean all your authentication mechanisms should be based on access tokens. Your API keys would allow you to get an access token that would be actually used for authentication.
As far as I understand, you have two kinds of users of your applications:
End-users using the Web UI (login with password through OAuth2)
Applications (login with API keys)
So I would implement these two kinds of users and make them the ability to get access tokens. Access tokens will be used in both cases to access the RESTful services.
In addition, I think that this answer can give you some other hints: Securing my REST API with OAuth while still allowing authentication via third party OAuth providers (using DotNetOpenAuth).
Hope it answers your question.
Thierry
Thank you for your answer.
I'm actually quite experience with OAuth2 itself, my question was more targeted to API keys. I like the idea of an API key exchanging an access token but I think that does not work. The API key is fixed and does not change, while the access token can expires.
The question is: how the app can know if this is an access token or API keys. I mean, ok, let's say that in my database, each user has an "api_key" column in their database.
Contrary to an access token, the api_key does not expires (although the user can eventually rotate it). What I want, as I told, is homogeneous handling of authentication.
Case 1: my own web app do API calls
The workflow is as follow, using OAuth2:
User enters his mail/password.
Authorization server returns a temporary access token (eg.: "abc").
In the web app, all API calls are done using this token. For instance: "/payments/1" with Authorization header: "Bearer abc".
Nice and simple.
Case 2: the user has an API key, that does not expire and can be used privately in their own app
Obviously, the authorization mechanism must stay the same. So:
User goes into his account, and read that his API key is "def".
In their server code, they can do the same call, with same authentication mechanism. So he can call "/payments/1" with Authorization: "Bearer def".
And it must work. As you can see, nothing has changed in both examples. They access the same resource, same authorization mechanism... but in one case we have an access token and in other case we have an API key. And I have no idea how I should implement that both from a database point of view and in the authorization code.
One potential idea I had is using different auth mechanism. For OAuth, it would be "Authorization: Bearer accessToken", while for API it would be a Basic authentication: "Authorization: Basic apiKey".
Does this sound good?

OAuth2 User Credentials Grant Security

I have a couple security questions on the OAuth 2.0 User Credential Grant type and possible security attacks. So from what I understand so far, when I exchange my users username password client ID and client secret for an access token over HTTPS that is completely safe. Now say for an example if I have a first party mobile application for a service that is doing the user authentication and I keep the access token on the device.
If the access token is compromised some how the compromised access token can be used to make subsequent requests to say for example the API service. Is there any way to prevent this other than just not getting the access token out there?
If your doing all API requests over HTTPS I shouldn't have to be worried what so ever about the access token being compromised over the wire or have to worry about any replay attacks?
So basically my concerns about possible security flaws with this specific type of grant. I'm pretty sure if the access token doesn't get compromised and all traffic is over SSL it should be fine.
I'd love to hear someone's expert opinion not the biggest OAuth person.
If the access token is compromised, the app that now has it CAN misuse it. Since access tokens are short lived, and are mapped to certain permissions only - the damage would be limited to say 10 minutes access to a single resource! (tokens are generated for apps that are registered for a scope, the scopes are mapped to permissions.)
If you are working on a first party app, why do you want to store the token on device? You can think of using the authorization code flow and not the implicit grant flow. That way the access token is always with the server and not on the device locally.