How to authenticate an app instead of an user with django rest framework? - authentication

By default, TokenAuthentication creates one token for each user (User access tokens), what makes sense for an API accessed only by end users.
But to integrate with other applications, would be more suitable to authenticate the application itself (App access tokens), instead of to make the application access the API on behalf of a given user.
My question is how to achieve that with Django rest framework. Should I extend the tokens model to add a FK to the applications table or there is an "easy" way? Any tips?

If i understand your problem problem properly Instead of per user a token you would like to have per device ( app ) an authentication token. There are some well used third party app's like django-rest-knox or jwt provide that. No need to do this manually.
Though i prefer django-rest-knox as it has delete all token facility. Which is very useful in case of lost or compromise device.

Related

Is JWT right for me?

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.

IdentityServer4 retrieve both cookie and token during login

I have got an IdentityServer4 project where i protect an API. Inside the Identity Server project i am developing a mini dashboard where i have added some basic administration features like adding clients, scopes, webhooks etc. Also, inside this dashboard, i want to display some information that comes from the API. The problem is that i need not only a cookie (to login to the Identity Server) but also a user token to communicate with the API and fetch the required data. Is this a valid scenario?
I could of course make a separate call, during the initial login, and get a token by using the user's credentials but this does not sound like the best practise, so i want to avoid it at first place.
Also this dashboard could be a completely separate project and use the Hybrid Flow to achieve the desired functionality but i did not want to create a third project for this. Do you believe this is the optimal solution though?
Thank you in advance for your opinions and answers.

IdentityServer4 personal access token (github-like) or API key for third party clients

Our current setup is
IdentityServer4
Angular + ASP.NET Core application
Authentication for the app via implicit flow/oidc.
We want to provide APIs for customers, i.e. third party clients, with restricted access (separate set/subset of claims). These clients are mostly non-interactive scripts that download data.
This means that we cannot use any flow which (occasionally) requires user interaction. Personal access tokens, like in github, or some other generate once, reuse for a long time API key or token would be needed.
The long token lifetime would not be a security issue, because the token should only allow access to a few read-only APIs and only for that customer's data - so the responsibility to handle the token(s) falls onto the customer.
The customer should be able to create and revoke such API-access tokens based on their claims. Some users might only claims to access certain APIs.
It would be good if we could later prevent that the user re-uses the same token for multiple clients because of licensing requirements but that is perhaps an entirely new question
How could I achieve this?
I thought about doing this via a custom grant, similar to a delegation grant: user uses app, which calls the asp.net core API, which performs auth with that custom grant, persists that token somewhere (just a plain table in the database full of customer-api-only tokens? I'm not sure about that) and shows it to the user - which can also retrieve it later from storage.
I'm thinking about doing the "delegate"-authentication via our API so that we don't leak the secrets into the Angular application.
I think that we then should be able to have either long-lived access tokens or at least refresh tokens via that custom grant.
2017-12-12 how I think I could solve it
We want a process where the user generates something in our application (i.e. via our client) and this something can later be used by the user's third party client to access the API - or request an access token and then access the API.
We want this access to be tied to the user. This includes
- Disabled user
- Lockout
- Specific claims (e.g. tenant)
This does not lend itself well to a solution that issues access tokens directly, because the token would remain valid even if the user was disabled or locked out. Which means that we cannot use a custom grant or IdentityServerTools to issue tokens directly.
Therefore we should use the client credentials grant, or something similar to it, as this could yield new, short-lived access tokens.
User actually generates a new client, which is pre-filled with claims from the user (such as the tenant - which is immutable) and has a claim that corresponds with the user. This happens transparently. Password should be user-supplied with the option to change it. We only store the relation between user and issued client-ids, no passwords.
We have to create a custom grant, which works similar to client credentials, but also checks if the corresponding user is active etc. (which I think should be possible by injecting UserManager)
Resulting access token lifetime is short, interaction with our APIs is expected to be short-lived.
Assuming it is safe and easy enough to write such a grant, we should be able to cover everything we need.
Of course, I might have completely overlooked something :)

django-rest-framework Token Auth and logout

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.

Are Tokens based on Cookies Restful?

I'm building some RESTful API for my project based on Play Framework 2.X.
My focus is on the authentication mechanism that I implemented.
Currently, I make use of SecureSocial.
The workflow is:
An anonymous user calls a secured API
Server grabs any cookie Id (kind of authentication token) and checks for matching in the Play 2 cache. (cache contains an association between cookie Id (randomly generated) and the user Id, accessible from database.
If any matched, user is authorized to process its expected service.
If none matched, user is redirected to a login page, and when filled with valid credentials (email/password), server stores its corresponding authentication data on Play 2 cache, and sends the newly created Cookie containing only a custom Id (authentication token) to user and of course, secured through SSL.
While the cookie/token doesn't expire, the user can call secured api (of course, if authorized)
The whole works great.
However, after some search, I came across this post, and ...I wonder if I'm in the right way.
Indeed, dealing with cookies ("sessions" in Play's term), would break the rule Restfulness.
Because an api really considered as stateless should be called with ALL the needed data at once (credentials/tokens etc..). The solution I implemented needs both calls: one to authenticate, the other to call the secured API.
I want to make things well, and I wonder some things:
What about the use of Api keys? Should I implement a solution using them instead of this SecureSocial workflow? Api Keys would be sent at EVERY API CALL, in order to keep restfulness.
I think about it since I want my APIs to be reached by some webapps, mobiles and other kind of clients. None of all are forced to manage cookies.
What about OAuth? Should I really need it? Would it replace totally the usage of simple api keys? Always with this objective of several clients, this known protocol would be a great way to manage authentication and authorization.
In one word, should I implement another mechanism in order to be Restful compliant?
this is quite an old Q, but still worth answering as it may interest others.
REST does mandate statelessness, but authorization is a common exception when implementing.
The solution you described requires a single authorization process, followed by numerous service calls based on authorized cookie. This is analog to api keys or OAuth. There's nothing wrong with cookies as long as the service isn't of high-security nature and that you expire then after a reasonable time.
Integrating OAuth into your service sounds a bit of an overkill and is recommended only if you expose the API to 3rd parties (outside your organization).