I would like to implement quotas for users accessing my API but I'm not sure the flow I have in mind is the way to do by simply reading documentation from several API management solutions.
Currently, my flow could be described as follows :
The user provides credentials to the app
The app calls my Authorization Server for validation. The token is returned to the user if successful.
In the following requests, the app will validate the token (Authorization header) against the Authorization Server before accessing the service.
My problem is that I cannot implement quotas based on tokens since my users would be able to get a new token to avoid the limit. According to your experience, is it possible to manage quota by users at the gateway level or should I change my API authentication method?
Best regards,
When we speak of api and token the most used model of communication is the protocol OAuth 2.0.
Through it, API users must authenticate to their respective OAuth authentication server (it could be a third-party server, eg facebook or google).
With the token in hand and this token is a token with a limited lifetime, the exposed API must validate this token against the OAuth resource server which will identify who will be the client / application that is requesting.
Therefore, using OAuth token it will be possible to identify the requester.
Regarding quota control if you will not use any API Management / Gateway market player (Ex: apigee) you must implement this control with a high-performance query engine. For a simpler solution a key value pair database could solve this problem (eg redis).
Related
Our company is using Microsoft AD for user management and authentication, also the authorization is done using the AD groups/roles. In the most 3rd party applications the users can authenticate with their AD accounts.
Now we are developing new applications, which should use an internal API. Therefor we created a new enterprise app in our Microsoft tenant and defined a couple of roles.
On the client side it is the normal flow - users authenticate with their accounts and the client receives the access token it should send to the API. And here is the point where I am not sure what is the best way to implement it.
Since all the users already exist in the AD, there is no need to only use access token to get the user identifier and create/link the user in the internal database - I want to use the AD users and to be able to verify the roles and use them in the services behind the API gateway "as is". But the roles are not stored in the access token, so I assume, I have to request them from Microsoft separately. But also I do not want to request them every time a user sends a request to my API and want to rely on the token the cliends sends to me and which I can verify.
So what is the best way to implement it? Should I create a new Bearer JWT in our own auth service, containing all information I need, and provide it to the client, so that it sends it to me every time? Should client use this token for authorizing the user as well? But it also can request the IDToken from Microsoft? Would our internal token replace IDToken and Access Token? Or should we just use IDToken for requests to the API?
Creating an own token looks like an overhead to me, since we only work with AD users but I also don't want to use IDToken for authorization in the API.
In an OAuth architecture your apps (primarily APIs) accept tokens from the Authorization Server (Azure AD in your case). You then use these tokens to authorize requests for data based on Scopes and Claims. Avoid issuing your own tokens and use AS tokens consistently. It feels like you then need to deal with domain specific claims, which is tricky, and these are the main concerns:
Option 1: Custom Claims in JWT Access Tokens
This requires Azure AD to reach out to your internal API at the time of token issuance. This is the preferred option but it may not be supported - or possible - depending on the provider and hosting infrastructure.
Option 2: Custom Claims via Lookup
Here is some example C# code of mine that shows a technique where you form a custom claims principal in the target API. The extra claims are looked up (typically from a database) when the access token is first received, then cached for future requests with the same access token. It is not ideal but I have had to use it in the past due to vendor limitations.
Confidential Internet Tokens
Be careful when including claims in access tokens to not reveal sensitive data to internet clients, eg web or mobile apps. Aim to use the phantom token pattern if possible, so that you do not reveal any sensitive data. If the Authorization Server does not support issuing reference tokens, then option 2 above may be the least bad option.
I'm integrating several web sites/services into my application. I use iframes (or webview for Vue Electron) for UI integration and I also use API to implement cross-communication between those services.
At the moment I have to go through OAuth 2 authentication twice for each service: once as part of natural authentication in iframe and another when I ask the user to give me access to this service (for api reasons).
Is there any way to streamline this process?
The state of the art response would be to modify your application completely.
You should have 1 SPA application and not iframe
This application would authenticate to get OAuth2 token
This application would then call the backend (access multiple backend, or access on api management layer that call backends).
Thing is, with this you can have 2 strategies :
give all permission (scope) at 1st authentication
give the smalled scope possible at 1st authentication, then when needed "reauthenticate" (in fact validate new scope) to get new access token
When an API want to call another API, you have also 3 strategies:
you simply use the same client token the API receive to the service your API call (no human interaction needed)
your API generate a token from a service account (using ROPC authentication scheme) or via a client credential scheme (the access token will be valid but usually not be bind to a real user), (no human interaction needed). (the API will be the client of the 2nd API)
your identity provider have an endpoint to transform access token : Your API can give the client access token, and authorization server will transform this with the client_id of your API. You send this token to 2ndAPI ( token will show subject of your UI application, but client ID will be the 1st API clientId) (no human interaction needed)
Now if you use IFrame with multiple sub-application on the same domain (the domain need to be exactly the same!), it is possible to share the same access token for instance via local storage. (security is not top notch)
You will probably need to authenticate with a bigger scope list sometime but it is your only option. You will simulate a single page application, but issue is that you will have potentially different client_id depending first application you authenticate to.
Edit: Multiple authorization server
From your comment, you have multiple authorization server. One strategy could be to ask user to authenticate, your application can then get an access_token and a refresh_token.
Depending on your authorization server, refresh_token can be used a lot / on a long period of time, so that if you store it somewhere, the next time the user visit your application, your application can silently get an access_token from this refresh token. Your application have then access to remove api without newer interaction from your user.
Of course, this means you have to save this token the most safely you can.
By using OpenID Connect you could combine authentication and authorization in a one step and get both an id_token to logon your user to your app as well as an access_token to access APIs in a single authentication response.
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.
We're looking to implement web (external user) SSO and an API gateway to support web apps and mobile apps, and potentially 3rd party apps and even B2B scenarios.
My thought is to have the SSO gateway handle user-level access to websites and APIs, authenticating end users using OAuth or OpenID Connect.
Sitting behind this, for any API URLs, is the API gateway. This is intended to handle the client-/application-level authentication using something like a client ID and secret.
The idea would be that the user would log into a website or mobile app, and then if/when that app needed to call an API it would need to send its own credentials (client credentials flow) as well as a bearer token proving who the user is as well (resource owner password flow).
The client credentials are less about security and more about coarse-grained access to API functions, giving visibility of API usage, traffic shaping, SLAs etc., but the user identity is needed to enforce data-level authorisation downstream.
Most API gateways I've looked at appear to only support a single level of authentication, e.g. we're looking at Apigee at the moment that can use OAuth to authentication to handle either a user or an app, but it's not obvious how to do both at once.
Is there any way to get the SSO gateway's user bearer token to play nicely with the API gateway's client bearer token or credentials, preferably in a fairly standards-based way? Or do we just have to hack it so that one comes through in the auth header and the other in the payload? Or is there a way to have a combined approach (e.g. hybrid bearer token) that can serve both purposes at once?
I'm kind of surprised that with all the work going on in identity management (OAuth2, OpenID Connect, UMA, etc.) nobody is looking at a way of handling simultaneously the multiple levels of authentication - user, client, device, etc.
Unfortunately I don't have enough reputation points to comment on the previous post, so I'll add my two cents here. Full disclosure: I work for Apigee.
http://apigee.com/docs/api-services/content/oauthv2-policy#accesstokenelement explains how to give the access token to the Apigee OAuthV2 policy in a place other than the Authorization header. If you've stored the SSO bearer token as an attribute of the Apigee OAuth token then once the Apigee token is validated you'll automatically get the SSO bearer token as a flow variable and can use it as needed.
For example, if you send the token as a "token" query parameter on the request you can code the following in the OAuthV2 policy
request.queryparam.token
and the policy will pull it from that query parameter.
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.