How to implement OAuth when the resource and auth servers are same - django

I have a Django Rest API with JWT authentication which is the backend for a Angular frontend. There are many clients who use the service with our frontend. Now some enterprise clients wanted to integrate the APIs from their system's backend. I don't want to remove JWT from current APIs. I am planning to create new APIs in the same backend with OAuth token for those users.
I wonder what is the best way to implement OAuth for this scenario.
I am thinking Client Credentials grant type is the best way.
Question1: Am I right that client credentials is the right approach ?
For those enterprise users, it is sufficient they get just access token through the UI interface so that they can access all our APIs.
But here the problem is one additional step of getting the Client ID and Client Secret first and using that to get Access Token.
Question 2: What is the use of client ID and client secret ?
Question3: Should my backend hide the process of generating Client ID and Client secret and just give Access token (or) give them Client ID and Client Secret and ask then to generate access token ?
Question 4: If I am giving them Access Token without client id and secret, is that fine to have infinite expiry time? and
TLDR; How to implement OAuth when the resource server and auth servers are same ?

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.
Question1: Am I right that client credentials is the right approach ?
I think you can use CC if there is no user level logics in your backend. If userlevel involved, may be ROPC is a better choice
Question 2: What is the use of client ID and client secret ?
Client ID and Client Secret is very similar to username and password in an application level, which is used to obtain bearer token.
Question3: Should my backend hide the process of generating Client ID and Client secret and just give Access token (or) give them Client ID and Client Secret and ask then to generate access token ?
If you are implementing oAuth2, your consumer should create the access token. But looking at your use case, may be even a simple hash of userId+timestamp is sufficient. ;)

Question1: Am I right that client credentials is the right approach ?
Yes. Providing the new APIs do not need to be called in the context of an end user.
Question 2: What is the use of client ID and client secret ?
The client ID allows the auth server to identify the application
requesting the token (it's often carried through to the access token
too, allowing the API to identify the calling application).
The client Secret means the auth server can trust that the client is
genuinely who he says he is as only he should have the private client
secret for his public client ID.
It's effectively a username and password in this scenario.
Question3: Should my backend hide the process of generating Client ID
and Client secret and just give Access token (or) give them Client ID
and Client Secret and ask then to generate access token ?
Your Auth server should issue the client credentials to the application once and the application should provide those credentials every time they wish to obtain a token via the client credentials grant type.

authorization code grant, or implicit grant might be more suitable for this scenario. The first one allows you to add an authentication step before the tokens are returned to the users (might be useful if you want to integrate your JWT authentication to this as well) and the second one is mainly used for single-page applications, and does not include an intermediate authentication step. This one would be useful if you want to improve efficiency.
client_id and client_secret are given to you when you register a client application in your identity provider(authorization server). This client application does not mean an application or an API belonging to your clients, but your own application to which you plan to incorporate OAuth(and OIDC). These two parameters are useful when making the requests to authorization in order to obtain tokens. The server uses those values to determine whether the request is made by a valid application. Only you have access to those values as you will be the one who's registering the application with the server.
I think this question is answered in the previous section.
I think it would be better if you go through this before doing any implementation. It provides most of the basic knowledge you should have before implementing an OAuth system. I hope this answer was useful to you.

Related

Token exchange flow - how to register and login user

Here is my understanding of the token exchange flow:
First i should follow this section of the docs: https://developers.tapkey.io/api/authentication/identity_providers/
After I created identity provider, I want to register my test user using this endpoint https://developers.tapkey.io/openapi/tapkey_access_management_web_api_v1/#/Identity%20Provider%20Users/OwnerIdentityProviderUsers_Put
First question related to the endpoint above is, how do i authorize this request? On swagger documentation there is only clientCredential and AuthorizationCodeAuth options. Does this mean i need one of this types of authorization, so that i can authorize request from my server (from application point of view, lets say).
For endpoints like:
List all owners
Register user
etc.
Now let's say i registered a user, using client credentials to authorize a request.
I am trying to login, following Token Exchange section in docs.
There it says I need to use this POST https://login.tapkey.com/connect/token, i am formatting the jwt as said in the docs, and sending to this endpoint. I am using client_id from my token exchange oAuth client. I got an error with the following message, which is pretty clear to me, but i can't find the solution for it.
{ error: 'unauthorized_client', error_description: 'Client not authorized' }
Mostly, the listet authentication types in the swagger documents are to be able to test the endpoints within the swagger ui. So it is possible to create a oAuth client, pass it to the swagger ui and test the endpoints.
The endpoints itself do not differ between authentication type.
Depending on the purposes the authentication method should be used.
Authorization Code Flow
If you have a service, which works on behalf of a Tapkey user, the authorization code flow should be used.
E.g. you have a booking platform, and your customer should be able to grant access to locks owned by them.
It is not possible to use the authorization code flow to login into the Tapkey Mobile SDK and unlock locks. An authorization client can not request the therefore required scopes.
Client Credential Flow
For server 2 server communication to manage your services, e.g. for adding identity provider users or managing locks which are owned by your services, then the client credential flow would be a good choice.
For that, the client credential client must be authorized as an administrator to the specific locking system.
Token Exchange Flow
To login your users into your app and using the Tapkey Mobile SDK to unlock locks, you have to sign your own JWT tokens on your server and exchange then on the client with the token exchange flow.
Please be aware: It is not possible to use the authorization code flow to sign in as a Tapkey user and then exchange it via token exchange.

Django login required between two servers

I have two servers.
Server A - this is whole bussines logic and API for mobile application.
Server B - in simply words, this is a webpage.
And now, I need to authenticate user on B but, by the 'user-data' from A.
E.G.
On A server I have user with loggin/password. And I need to use this same login/password on B server. There is some nice solution for that? Or just use tokens?
Presumed that you have an authentication mechanism in your server A.
You have to use your server A as an Identity provider. Request to your B-server should have a session header. If this session is not valid in B-server then you have to ask for credential from the web user and forward this request to your Identity Provider(Server-A). If Server-A can identify the given credential, initiate a session in server-B for this user for a particular time frame. You have to manage this session in the Server-B.
When this user logged out from server-B just destroy the session.
tokens should be fine such as a bearer token on the Authorization header. There are different strategies such as opaque tokens vs JWTs, etc.
I actually did a write up on API authentication tutorial and security holes:
https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/

OAuth-2.0 resource servers token validation in distributed environment

I'm going to make a REST web service with many resource servers (implemented in different programming languages) and one authorization server.
My question is about token validation in the resource servers. Let's say that a resource server cannot connect to the database and check the token info there.
I have read this thread: OAuth v2 communication between authentication and resource server
And I like the idea to make an API in the authorization server, which will be responsible to "resolve" tokens. For example: https://oauth.example.tdl/tokeninfo?token=tokentovalidate
So my question: Should the /tokeninfo resource be "public"? I mean everyone who knows this endpoint will be able to validate tokens..
Wouldn't it be better to make this "private"? I mean https://oauth.example.tdl/tokeninfo?access_token=valid_token&token=tokentovalidate
But then my resource server will have to authorize itself before validating tokens.. too many requests, I think..
If you know more strategies to validate tokens between resource server and authorization server - tell me, because I'm pretty new to OAuth.
Should the token verification API be public?
In terms of authentication, if should of course be an authenticated API, and the access token that you use to call it is the access token you want to verify. RFC 6750 explains how to do that. Typically, the token is sent in the Authorization header, or as a Uri query parameter.
Alternatively, for more security, you require the client id and client secret to secure the call, either by passing them as parameters, either by obtaining an access token for the client using the Client Credentials Grant.
Be careful what information you return from the API. You should only return information that does not require a specific scope that has to be authorized by the resource owner.
For a real life example, see the Google implementation or the implementation from The Identity Hub. For the Facebook implementation, see the section "Confirming identity" on Manually Build a Login Flow.

End user authentication for RESTful web services

I have an internal-facing RESTful web service. There are various client applications using the service, and the client apps themselves have end users. The web service needs to authorize requests based on the end user identities.
The question: What are the typical options for authenticating the end user here? That is, I want to authenticate the user, not the client application. (I don't mind if authenticating the client application is part of the scheme, but ultimately I need to know that the end user is who I think he or she is.)
One possible scheme, for example, would be to have per-client system accounts, and then have the client simply assert the user's identity (e.g. in an HTTP request header, say). So we authenticate the client application and delegate user authentication to the client. I don't think this is a very strong scheme, though, because it depends too much on keeping the system account credentials secret. I have seen too many examples of people e-mailing system account credentials around to put much faith in this sort of approach.
Another approach might be to have the client app, upon user login, use the user's credentials to get a token from the API, and then use that token for subsequent API requests. That way the authentication is user-specific without requiring the client app to hang onto the username/password credentials.
Anyway I'd like to have a better sense for the range of options I should be considering here.
The problem that you describe with "delegated authentication" is a real one. It means that a "client application" using it's credentials has access to the whole breadth of user data. This access can be used maliciously (for example a "semi-trusted" app harvesting api data) or negligently (for example an app accidentally exposing a Direct Object Reference Vulnerability - https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References)
Probably the most prevalent "token based" scheme is OAuth2 (http://oauth.net/2/), and the precursor, OAuth, which many sites choose to continue to use.
OAuth2 has a number of roles:
resource owner (the user in your case)
resource server (your api)
client (the apps you talk about)
authorization server (not clear who or what would fulfil this role in your case)
The basic scheme is that the resource owner authenticates using their credentials directly with the authorization server. They are then asked if they want to grant some information (which may just be a persistent identifier, or a description of the information exposed by your api) to some client. When they accept an 'auth code' is sent to the client and they use that (combined with their own credentials) to receive an 'access token'. This access token can then be used to authenticate against the resource server (which can check it's authenticity back against the authorization server).
Normally the way this is used is that the authorization server and the resource server are owned and managed by the same entity (for example google and facebook would fulfil this role) and then clients are independently managed.
The scheme can also be used internally within an organisation without the "explicit grant" which can still at least confirm that a specific end-user is present before releasing any data from an api.

OAuth 2.0 client ids in Django/tastypie implementation

I'm trying to implement OAuth 2.0 for my API. I'm using a third party library to act as the basic OAuth provider, django-oauth2-provider,
and Tastypie as the framework. Those details shouldn't matter too much. The OAuth 2.0 works -- when a user is created, an OAuth 2 client
that manages the user's secret_key and their id is created. A customer can then supply the user ID they get back from the user creation
endpoint along with their username and password to get an access token which allows them to use API endpoints.·
Where I run into issues is retrieving the client id (which must be passed into requests for the access token). Obviously when a user is first created
I can return the client_id with the HTTP response. After that, however, there will obviously be cases where the user doesn't have their client id·
stored locally (this is a traditional user/app setup, not something like Google APIs where your client id is always visible). I want to protect
GET requests to the customer resource with OAuth, but that means I can't query the API for a given user's client ID. And it seems like the whole point
of OAuth is defeated if I can always just pass in a username and password to retrieve my client id from some oauth endpoint. Am I thinking about this wrong?
Also, from reading the OAuth specs I'm under the impression that a client id and client secret are all that should be supplied for getting granted an access token. Yet the implementation I'm using defaults to forcing the user to supply a client id, client secret, username, and password. I've overridden the implementation to require only the client id and secret, but I want to make sure that was the right call and I'm not missing something.
Edit for flup's response:
I'm dealing with a Django API as the resource server, and a user of an iPhone app as the resource owner. The iPhone app is directly associated with the server -- in other words, there are no third parties involved here and no plans to involve them in the future; all software is ours. I would think that the password flow would be what I would need in that case. Indeed, that seems to be what django-oauth2-provider supplies by default. I'd like to stay somewhat in line with what they are doing to not have to completely reinvent the wheel.
The goal of oauth2 is to let the resource owner give a client a valet key which authorizes it to access certain resources on your server on his behalf.
If there are no third parties involved, there is no client to authorize and no need to use oauth2.
Instead, you could use the standard authentication mechanisms present in tastypie.