I'm about to code up a new RESTful API, in the design phase. Several folks I've talked to keep telling me about OAuth so I'm doing some homework.
One thing I don't really see out there, and maybe not many (no one?) is doing it, but I'd like this API I'm working on to function with or without the context of a user.
Basically, if you call the API with an authenticated user, some parameters are loaded from the user's preferences. But I'd like to structure it such that the same calls can be invoked without a user in which case they require additional parameters that would have been read from a user account.
Would this be cumbersome to implement, being that I'd like to use OAuth for the authentication component of the user-based method signatures? Would it be better to just build them as two separate APIs?
Another goal I have is to use the same application key/application secret paradigm for both scenarios, if possible.
Just so you have a more concrete idea what I mean, imagine these to psuedo function signatures I'd like to support in my API
/**
* Search, when called with a user. Here I'd like to authenticate via OAuth
*/
function search(string search, object user)
/**
* Search, when called without a user requires more arguments.
* These calls require application key/application secret
* but no user authentication.
*/
function search(string search, object coupon_preferences, object store_preferences)
OAuth 2.0 (RFC 6749) defines the flow as Client Credentials Grant.
In the flow, a client application accesses the token endpoint and OAuth authorization server issues an access token to the client without any user authentication/authorization.
See "4.4 Client Credentials Grant" of RFC 6749 for details.
Related
I want to include the oauth2 authentication flow into my application, but also provide an internal database (regular register / login) as an authentication method.
I'm not that sure how to approach that behavior, as I would love to have one single state for the authentication. I've thought about exposing the authentication using the internal database as an OAuth2 application itself, therefor token management etc can be generalized.
This would be a basic example of my thought process:
To distinguish between the multiple OAuth providers, I'd have wrapped the actual token inside a JWT, which also contains the providers name (as well as have a spam protection in my backend, instead of spamming the actual provider).
I'm not sure if it's that good to store the actual user data in a database as well - But I'd need some kind of overview of registered users for the administrators to see - and maybe block or delete.
My questions in particular:
Should the OAuth token be wrapped in a JWT for identification of the provider?
Is it bad practice to store the user data in a database as well? (If not, how much data should be stored [username, ...] and when should the data be refreshed?)
Is there anything else I should keep in mind when doing the authentication flow as it is?
I've done a fair amount of research on the many different ways to authenticate and authorize users who use my frontend application to access my REST API. I've built a system that uses OAuth2 and JWT and need a sanity check since I'm working on this alone.
For a bit of background, my frontend is built using Vue.js and my API is built using Django with Django Rest Framework. My team is already planning on concurrently developing the mobile and desktop versions of this app which both would require authentication and authorization as well.
To keep things brief, I'll omit the alternative solutions I have and just talk about the most controversial one.
Right now, OAuth2 (my authorization server) grants users a JWT token using ROPC when they provide their email and password to my frontend client. I should note that my API (my resource server) and authorization server live on the same machine.
My application allows users to essentially signup using different plans (for example a free plan and a paid plan). When a user signs up for a free plan, I need the frontend application to not only disable certain features and elements in the UI, but also I need the authorization server and or resource server to limit what that user is allowed to query based on their plan.
The idea is when a user signs up or logs in, my authorization server will get the associated user record from the database and create a valid JWT with a claim attached that states the user's plan and maybe some other non-personal information. Then once signed it sends it off to the user where the frontend can enable/disable parts of the UI... etc. Hence, if a user logs in on mobile, we can customize the UI based on the same claim sent by the JWT.
My issue is that I don't know if this is a good way to go about it. It seems that everyone I've asked in my circle is split on using JWT or not. Those apposed mostly raise security issues, but, when from what I understand, many of the JWT security pitfalls are well documented and can be avoided just using some commonsense as with any other session/token-based authentication. I'm starting to get analysis paralysis. Please help.
CLASSIFICATION
I would say this is really an API Authorization question, as opposed to an OAuth question:
The role of the Authorization Server and tokens is really just to prove the user's identity
Product specific logic comes after the user logs in and is generally best handled in your app
MY PREFERENCES
Here is how I would handle it:
Save the plan type to your product data when the user signs up
After login, look up the user from the access token
Then look up the user's plan type from your product data
Produce a Claims / Principal object in your API containing both
Enforce business rules based on the plan type claim
I would aim for a Claims object something like this:
class ApiClaims {
// The user id in the access token
userId: string;
// The email
email: string;
// The plan type
planType: string;
// Other claims from the token
// Other claims from product data, eg user roles
}
RESOURCES
If interested in this approach, these blog posts of mine may be of interest:
User Data Management
API Authorization
JWT?
You need some kind of API credential that is sent in HTTPS messages and is web and mobile friendly, so I would use JWTs. You could follow the same pattern with any API credential though.
It depends on what you are trying to protect of course, but JWT bearer tokens are an industry standard. Since you control both the client and the authorization server, you can implement it however you like.
I would look into changing Resource Owner Password Credentials flow to authorization code flow. It will enable you to use social authentication providers like Google or Facebook to sign in users (while still maintaining plan info in your own service). Chances are that people trust those companies more to keep their credentials safe than your company, and it allows you to benefit from any authentication features (MFA) those companies implement.
Also, if you want the clients to read the contents of the token, you should use OpenID Connect id_tokens, as those are guarenteed to be in JWT format.
I'm starting a new project which will have to manage many access tokens for many different APIs. So I was wondering if it was good practice to provide the access tokens to the different classes implementing the API calls or if the tokens should be better encapsulated.
Currently, I see two options:
every API class constructs their own requests (mostly HTTPS requests), gets the access token from an authentication interface and adds that token to the request in a manner required for that API
the authentication interface accepts the request from the API class and adds the token to it before actually dispatching the request.
With the latter option, the API class would never see the token, but it would be difficult to foresee all the options how to add the token to the request (header, GET parameter, or totally different ways).
What should be best practice in this case?
Generally an access token contains information such as "is this user privileged" and other authorization-related claims that go beyond authentication.
That means that the authentication service alone cannot deal with these claims, and the API class needs to be able to see them.
Therefore, your API classes should have the opportunity to add claims to the access token. Whether or not they are the ones constructing the token itself is not important.
As far as understood, obtain_auth_token view works as a login functionality. You provide credentials and get the token back. What will be the logout? Should I delete the token on logout? What would be the best practice?
If deleting is OK, then how do I handle multiple clients at the same time. Say, the user logs out from mobile device but wants to stay logged in on the web. The Token model currently has a OneToOne relationship to User.
Please give me some advice. Thanks
The TokenAuthentication provided by Django REST framework is intended to be used as a very simple token authentication. What I mean by that is, you get
A simple token that ties an API consumer to a user
...that doesn't rotate by default
...that doesn't expire by default
...that is shared between API consumers (single token)
If you are looking for anything more advanced than that, you usually have to look into a different token authentication method. This can be as simple as subclassing the standard TokenAuthentication classes and views (as linked), but the Token model is not easily swappable. This means that changing the user field to a ForeignKey, allowing you to have multiple tokens for a user, is not easy to implement.
Luckily, Django REST framework does support other authentication methods, such as OAuth and JSON Web Tokens, both of which support multiple tokens for users. You can find a comparison of the common authentication classes at this Stack Overflow answer.
Why use the proposed OpenID OAuth Extension over another OAuth-based protocol?
Discovery doesn't seem to be a feature. Although the consumer only needs a claimed identifier to start the authentication process, any authorization will still require that the consumer knows the access token URL, signature methods, and have a shared key/secret with the provider.
One benefit is that there's a specified way to ask for specific authorizations, the openid.oauth.scope argument to the authentication request. And one specific benefit for this is that authentication only - for the benefit of the consumer only, with no verifiable token - is defined for free and can be performed without worrying about keeping track of outstanding tokens or the resources they might require.
Are there examples of alternative ways in use to specify the scopes to be requested, perhaps with something in OpenID discovery? Or could this be handled effectively with some kind of REST navigation before the OAuth process, where one of several request token URLs specific to the desired scopes is discovered by interpreting hypertext starting from a well-known URL?
I am researching a delegated authentication and authorization system with several authorization scopes, where the scopes are relevant for different interactions. In other words, the consumer needs to tell the provider which scopes should be presented to the user for authorization.
The OpenID+OAuth extension really has only one significant advantage over standard OAuth:
If you need to authenticate the user and access the user's private data, and the OpenID Provider happens to also be the OAuth Service Provider (the user authenticates with the same service that holds his private data), then the extension will help the user have just one redirect to the OP+SP instead of two separate ones. For the user, this is a huge usability win -- if he happens to be authenticating with his SP.
The risks of supporting the extension is adequately supporting users whose OP and SP are not the same entity (you don't want to say you'll support the extension and then inadvertently lock out users whose OP is not also their SP).
Keep in mind what you really need to know. If you only want to access the user's private data, but don't really care who the user is that you're interacting with, use just OAuth. No reason for the user to give up his identity via OpenID if you're only downloading his photos to offer a photo printing service, for example, or if you already have a non-OpenID account for this user.