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?
Related
I am exploring possible solutions for creating something like "API Keys" to consume my API. The goal is to allow for users to generate one or many "API Keys" from the web app and use the static generated key from the CLI app.
The web app and the client app are already using standard OIDC with JWT tokens for authentication and authorization using RBAC (role-based access control). The CLI app can already authenticate the user through the standard browser flow (redirects the user to the browser to authenticate and exchange the token back to the client).
The "API Keys" solution I am trying to achieve should have some fine-grained options where it won't authenticate as the user, but will authorize the client on behalf of the user (something like the GitHub Personal Access Token).
To me it seems like a "solved problem" as multiple services provide this kind of feature and my goal is to do it the most standard way possible using the Oauth2/OIDC protocols but I can't find details on what parts of the protocols should be used.
Can anybody provide any guidance on how it is supposed to be done using the Oauth2/OIDC entities?
Can I achieve it by only using Role-based access control or do I need Resource-based access control?
It went through the path of creating a new client for each "API Key" created, but it didn't feel right to create so many clients in the realm.
Any guidance or links to any materials are appreciated.
Can anybody provide any guidance on how it is supposed to be done
using the Oauth2/OIDC entities?
OIDC is based on OAUth 2.0 so after user login you have id tokens, access token and refresh token on the backend side. To generate new access token without asking user for authentication data you should use refresh token: https://oauth.net/2/refresh-tokens/
Can I achieve it by only using Role-based access control or do I need
Resource-based access control?
resource-based access control is more flexible solution here, but if you business requirement is not complex, then role based might be enough.
It went through the path of creating a new client for each "API Key"
created, but it didn't feel right to create so many clients in the
realm.
It is one application so you should use one client with specific configuration for access token and roles/permissions for users.
Update:
We can use GitHub as an example:
User is authenticated during login
for OIDC code is exchanged for id token, access token and refresh token
session for user is set for web browser
User can request access token
in GitHub authenticated user can request github.com/settings/personal-access-tokens/new endpoint
request is accepted, because user is authenticated based on session
backend service responsible for returning access token can obtain new access token using refresh token from point 1.
access token is returned to GitHub user
To call your API in an OAuth way, CLI users must authenticate periodically. Resulting access tokens can be long lived, as for GitHub keys, if you judge that secure enough. The access token returned can be used exactly like an API key. There may be a little friction here between usability and security.
CONSOLE FLOW
The classic flow for a console app is to use the Native Apps Desktop Flow from RFC8252. This involves the user interactively signing in using the code flow, then receiving the response on a loopback URL. It is an interactive experience, but should only be required occasionally, as for GitHub tokens.
API KEYS
The access token returned is sent in the authorization header and you can use it as an API key. Access tokens can use a reference token format. to make them shorter and confidential, to prevent information disclosure. These will be more natural in a CLI.
API AUTHORIZATION
When your API is called, it must receive access tokens containing scopes and claims, to identify the user. This will enable you to authorize correctly and lock down permissions.
{
sub: 586368,
scope: repos_write,
topic: mobile,
subscription_level: silver
exp: ?
}
TOKEN REFRESH
Sometimes CLI access tokens are long lived, for convenience. A more secure option is for the CLI to use token refresh. It can then store a refresh token in OS secure storage, then renew access tokens seamlessly. My blog post has some screenshots on how this looks, and a desktop app that does not require login upon restart. The CLI needs to deal with expired access tokens and handle 401 responses.
DYNAMIC CLIENT REGISTRATION
Some developer portal scenarios use DCR. It is another option in your security toolbox. It could potentially enable a silent client per CLI user:
User runs a standard authentication flow with a DCR scope
This returns an access token that enables client registration
The resulting token is used to register a new client
This could potentially be a client ID and client secret used in a CLI
Afterwards, the user and client are bound together. Probably not immediately relevant, but worth knowing about.
I have to design a mobile application that interacts with a provided API to exchange data and info, and I've read about API security, Oauth 2, tokens, .... etc, but something still not clear to me, the following are the important points:
API provided by a 3rd party as a black box, no security implemented,
so you can query for data belongs to any user.
a user should use our application, sign in with a user/password and get access to his data only. (must be very
secure, because we should pay a lot if security was broken)
the solution needs to be implemented and self-hosted, not from a third party or cloud provider.
example of an API call:
....base url...../{subscriber-ID}/offers
the above call get the suitable offers for a subscriber whose ID is {subscriber-ID}, so obviously, without security, I can query offers for any subscriber, but my goal is to link between user/password and querying only data related to the desired user.
I read a lot, but I'm confused since I'm new to API security.
so where should I start? how can I benefit from Oauth 2 in my case? just need a roadmap, not how to implement.
oAuth2 using spring security is a solution for this requirement.
There are 4 grant types in oAuth2 which is meant for different scenarios.
client credential : the consumer (app) make calls to back-end using the bearer token created using apikey(or clientId) and secret only. Mostly used for anonymous calls where generic information is retrieved.
Resource owner password credential (ROPC) : the consumer (app) make calls using the bearer token created using apikey, secret, username and password. Mostly used when you(your authorization server) already know the users(user database is handled in your own system).
Authorization code : the consumer (app) make calls using the bearer token created using an authorization code. The authorization code is provided by a 3rd party (which actually has/manages the logged in user data) and the created authorization code linked to the logged in user. Google and Facebook log in for various sites is a typical example. Facebook/Google gives an authorization code for those websites and they exchange that code for a token.
Implicit grant : Mix of password credential and authorization code. Instead of authorization code, you get a bearer token from the 3rd party authorization server.
I have been searching a lot for a simple sample code for an authorization server, but never found one. So, I tried to create it myself which you can find here : https://github.com/abbinv/oauth2Server. Only ROPC and Client Credential is implemented.
It is not a 'beautiful' code. But i think you will get the basics.
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.
I thought that OAuth is basically a token based authentication specification but most of the time frameworks act as if there is a difference between them. For example, as shown in the picture below Jhipster asks whether to use an OAuth based or a token based authentication.
Aren't these the same thing ? What exactly is the difference since both includes tokens in their implementations ?
This is a good question -- there is a lot of confusion around tokens and OAuth.
First up, when you mention OAuth, you are likely referring to the OAuth2 standard. This is the latest version of the OAuth protocol, and is what most people are specifically talking about when they say 'OAuth'.
The OAuth protocol supports several different types of authentication and authorization (4 to be precise).
Secondly, the OAuth protocol works by authenticating users via tokens. The idea here is this:
Instead of having your user send their actual credentials to your server on every single request (like they would with Basic Auth, where a user sends their username/password to the server for each request), with OAuth you first exchange your user credentials for a 'token', and then authenticate users based on this 'token'.
The idea of OAuth is that by requiring users to pass their confidential credentials over the network less frequently, less bad things can happen. (This is the idea, anyhow.)
Now, here's where tokens come into play: the OAuth spec is built around the concept of tokens, but DOES NOT SPECIFY WHAT A TOKEN IS.
In the most 'general' sense, a token is just a string that uniquely identifies a user. That's it.
People realized this, and developed a new standard for creating tokens, called the JSON Web Token standard. This standard basically provides a set of rules for creating tokens in a very specific way, which makes tokens more useful for you in general.
JWTs let you do things like:
Cryptographically sign a token so you know that a token wasn't tampered with by a user.
Encrypt tokens so the contents cannot be read in plain text.
Embed JSON data INSIDE of a token string in a standard way.
Now, for the most part: pretty much everyone in the development community has agreed that if you're using any sort of OAuth, then the tokens you're using should be JSON Web Tokens.
OK! Now that we've covered the backstory, let me answer your question.
The choice you're making above is whether or not you want to enable the full OAuth2 specification for authentication / authorization (which is quite complex), or whether you simply want some basic 'token authentication'.
Because the OAuth protocol provides multiple different ways to authenticate in a STANDARDS COMPLIANT way, it adds a lot of complexity to most authentication systems.
Because of this, a lot of frameworks offer a 'dumbed down' version of the OAuth2 Password Grant flow, which essentially is a simple method where:
A user sends their username/password to your server at some URL like /login.
Your server generates a JWT token for the user.
Your server returns that token to the user.
The user stores this token in their cookies, mobile device, or possible API server, where they use it to make requests.
Again: the flow above is NOT OAuth compliant, but is a slightly simpler version that STILL uses tokens.
The main point here is that tokens (JWTs) are generally useful, and don't NEED to be paired with the OAuth flow.
I realize this is a wall of text, but hopefully it answers your question in more depth =)
OAuth is a specification for authorization not authentication
OAuth 2.0 is a specification for authorization, but NOT for authentication. RFC 6749, 3.1. Authorization Endpoint explicitly says as follows:
The authorization endpoint is used to interact with the resource owner
and obtain an authorization grant. The authorization server MUST first
verify the identity of the resource owner. The way in which the
authorization server authenticates the resource owner (e.g., username
and password login, session cookies) is beyond the scope of this
specification.
Only use OAuth if you want to give access to a third party service to your apis. Even when you are using OAuth you would need some kind of authentication (token based or session based etc) to authenticate the uses. OAuth is not designed for authentication.
see this question.
When you are requesting resource from a secured web service, you can provide an authentication token on the call. The token acts as "secret code" for accessing the resource.
OAuth is just specific type of token based authentication method.
I know this question has been asked a lot of times in varying shapes and forms, but I'm still quite unclear about a few things. It's confusing how resources about this topic around the Web refer to "user" without clear context. API keys are issued for users, and so are access tokens, but I don't think API key users, are the same as access token users.
Do you need to have different API keys for different instances of end user clients? For example if I build a mobile app for a third party API, does each instance keep their own API key? I don't think they do, but how do I tie API keys, and access tokens together to say that a certain request comes from this particular instance of an app authorized by a known user? If I were the auth provider, do I have to keep track of each of those?
API keys, and access tokens are usually represented by a pair of public, and shared keys. As a service provider (server side), which one do I use to verify the message I receive, the API key, or the access token? If I understand correctly, the idea is that each request should come with a signature derived from the secret part of the API key so that the server can check that it comes from a trusted client. Now what use do I have for access token secret? I know the access token is used to verify that a system user has authorized the app to carry operations on their behalf, but which part of the message does the access token secret be useful for?
Is a hash generated from a (secured) random number, and a time stamp salt a good API key generation strategy?
Are there (preferably open source, Java-based) frameworks that do most of these?
Let me try to answer as many of your queries as I can.
Apikey vs Access Token usage
First of all, apikeys are not used per user. Apikeys are assigned per
application (of a developer). A developer of a service signs up their application and obtains a
pair of keys.
On the other hand access tokens are issued for each
end-user in context of the usage (exception is Client Credential
grant).
Service providers can identify the application from the
apikey in use.
Service providers can identify the end-users using
access token attributes.
You should have any end-user APIs, that is an API that has end-user resources (data or context) associated, protected by 3 legged Oauth. So access token should be necessary for accessing those resources.
Developer-only resources can be protected by apikey or two-legged Oauth. Here I am referring to Oauth2 standards.
Oauth1 is preferred when there is no HTTPS is supported. This way the shared secret is not sent over unprotected channel. Instead it is used to generate a signature. I strongly suggest Oauth2 over HTTPs and avoid Oauth1 for ease of use. You and your API consumers would find Oauth2 to be much more simpler to implement and work with. Unless you have a specific reason to use Oauth v1
As a service provider you can use Apigee's Edge platform that provides Oauth 1 and 2. It is not opensource. However you can use it for free, until you need some high TPS or higher SLAs.