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.
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 a background task that runs periodically which needs to connect to a customer's Apigee OAuth2 protected API. From my understanding of OAuth2, a user must go to a sign in page on Apigee, and it will redirect to a return Url with a token. This is the way I have used previously on website projects. But in this scenario, there are no users, no website, and no return Url, it is just some code making a http request.
Is the above possible to do? Every google search I make is all about users logging in manually and getting a token to a return url.
I found some mention of 'Flows' and maybe there is some other 'Flow'? but its really hard to get a clear understanding of how it works because guides are focused on user interactive websites.
OAUTH 2.0 is an industry-standard for authorization. OAUTH 2.0 supports many authorization grant types, namely they are;
Authorization Code
Implicit
Resource Owner Password Credentials
Client Credentials
[Note that you may come up with your own custom grants as well if you are building or extending your authorization server - however it is beyond the scope of this question]
In the example you have provided, you are using the Authorization code grant type where you redirect to APIGEE and getting an authorization code. The APIGE server acts as the "intermediary between the client and resource owner" in OAUTH 2.0 terms.
For your new requirement, you should consider using the client-credentials grant type where the client is provided a client key and a secret. The client has the responsibility of calling the authorization server (like APIGEE in your previous example or anything else) and getting a token and then using that token in the subsequent requests.
I recommend you to read the ietf standard for oauth 2.0 to get a better understanding - Refer https://www.rfc-editor.org/rfc/rfc6749.
Make sure to read on "Roles" in this link well before diving onto the content of this document.
Good luck!
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 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?
I did some investigation about restful api authentication. Most people pointed to Oauth2 for restful api authentication. I looked into some of resouces, especially this link https://developers.google.com/accounts/docs/OAuth2.
It seems to me Oauth2 is for a third party app to access users' data in google/facebook(or other data provider).
Our problem is that we own the data, we don't need to access our client's any third party data and our clients don't have to any third party data. We want to protect our api with some sort of authentication.
For our case what is the convenient technologies for our restful api authentication ? We will expose our api like this
https://ourdomain.com/api/<endpoint>
Our clients can access a website first to register https://ourdomain.com and they should be able to get clientId and clientKey from our website for accessing apis. Our clients should be able to consume through some sort of authentication
In oAuth 2.0, there are several types of grant types. A grant type is just a way to exchange some sort of credentials for an access token. Typically oAuth refers to 3rd party usage with a Authorization Code Grant. This means redirecting the user to the resource owner's website for authentication, which will return back an Authorization Code.
This clearly doesn't make sense for 1st party oAuth use, since you ARE the resource owner. oAuth 2.0 has considered this and included the Resource Owner Password Credentials Grant for this purpose. In this case, you can exchange a username and password for an access token at the first party level.
See https://www.rfc-editor.org/rfc/rfc6749#section-4.3 for more details.
If I understand correctly, what you need it similar to OAuth in a way that you do the exact same thing minus granting a 3rd party app access to a user's resources.
In OAuth, there is a central system that manages authentication and authorization by checking an app's credentials + user's credentials and dishing out authorization tokens. There are multiple endpoints that will accept these authorization tokens.
The tokens are basically encrypted strings that contain info about the user's credentials and some other info that might be needed by your app.
What you need (i believe) is a similar authentication endpoint, that the client hits with its credentials and gets a token.
So,
i) Create a registration form/console where a client can register and get his credentials. Have a look at this.
ii) Define a HTTP endpoint where the user exchanges his credentials for an access token + refresh token.
iii) The client can hit the resource endpoint with the access tokens to make authenticated calls to any of your endpoint.
iv) At the back-end you'd need a common service that verifies the tokens and extracts info from it.
PS - This is just a minimal system, there would be a lot of security considerations like what if some unauthorized app gets access to some client's access tokens.
You can find much information about CSRF attacks, noonces, timestamps and other methods of mitigating security concerns.
Just to be clear with the original question:
OAuth2 needs at least a client and a server
OP was wondering how to secure a REST API, and why everyone is talking about third party authentication providers (Google, Facebook, ...)
There are 2 different needs here:
1 - Being able to secure a personal API (ourdomain.com)
Client Server
Consumers <----> Your API
2 - Being able to consume a public API (For example getting a user's Google contact list)
Client Server
You <----> Google APIs
OP actually needs the 1st: implement an OAuth2 server in front of its own API.
There are many existing implementations for all languages/frameworks on Github
Finally, here is one nice Oauth2 technical explanation, and I'm shamelessly taking one of its schemas here:
No I'm not working at Google, I'm just taking Google as a public API supplier example.