How do I restrict a user from accessing/updating another user's details? - api

I have an http endpoint /update-user-details that is authenticated by a JWT token.
There are two valid users in my system User1 and User2.
How do I restrict User1 from updating User2's details using the /update-user-details endpoint?

You have 3 options:
DIY: implement code yourself that will do it. That's what Chappie Johnson recommends in their response.
Externalize authorization logic: use an authorization framework to do the check for you. The way to externalize really depends on the framework you developed the API in. For instance, you could look into Flask Authorization for Python or Ruby CanCanCan or .NET claims.
Externalize authorization using a standard approach: Attribute-Based Access Control (ABAC) is actually what you are looking for. In ABAC you write policies that state what can and cannot happen. alfa and xacml are the two ways you can write policies. The good thing about this approach is that you can always change the policies without rewriting your API.

In your JWT you should have a claim in the body of the token that contains the user id of the requesting user. Before making an edit, you could check to see that the user_id value in your JWT matches the user_id value that user1 is attempting to edit. If the user_id's do not match, then reject the change.
String userId = getUserIdFromJwt();
if (!userId.equals("some user id")) {
throw new HttpUnauthorizedException("You do not have access to edit" +
"this resource.");
}
You have all the information about the current requesting user in the JWT so you are able to make assertions about the user.

Related

How do I use Auth0 roles to modify my API's behavior, rather than simply deny authorization?

My express.js backend has an endpoint which returns a list of what data the user is authorized to view. There are Auth0 roles corresponding to which segments of this data any given user is allowed to read. A user may have any number of these roles. However, when I tried to add role-based permissions to this endpoint, I realized that the Auth0 recommended middleware express-jwt-authz perhaps doesn't do what I intend: it simply authorizes/rejects based on the roles in the JWT. This endpoint only requires a user's session authorization, not the user's roles.
I want the endpoint to change its responses based on which Auth0 roles are associated with a user. The only solution I can think of is adding a row to my own database (which is not connected with Auth0) where I keep track of each user by the JWT sub property, and manage their roles/permissions from my backend. However, this seems like it would split roles between Auth0 and my application's database, and furthermore feels one step closer to rolling my own authentication system, which I do not want right now. Is there a way I can do this with Auth0 and express.js?
I was able to work around this by selecting "Add Permissions in the Access Token" in Auth0 in Applications > APIs > [my API] > Settings. Then I could view the permissions passed into req.user.permissions on my backend, and process them how I wanted there.

How to authorize different roles on a .Net 5 OAuth API

I have an IdentityServer4 application, a client application and a .Net 5 API. I want the client application to be able to talk to my API on the users behalf with an access token. Some users should be able to do admin requests while others should only be able to do normal user tasks.
I believe I need to add two scopes for these, api.admin and api.normal.
First question is where would I add these scopes in identityserver? Does the client request both scopes and just gets back whatever IS decides is right for that user?
Secondly, how do I validate what scopes are in the access token on my API. Method 1 should only be used if the access token contains the api.admin scope for eg.
Thanks!
First, scopes are something you typically hard-code in your client and it does not "vary" between users. It main purpose is to indicate what the "client" application want to have access to, not the user.
So you only need only one scope like "api".
Then you have different roles or claims in the access-token that describe what the authenticated user have access to.
You then use the authorization middleware in the API to determine what the user actually have access to.
Like what the picture below shows:
There is no reason that different scopes could not be requested by the client based on the user interacting with the client or even environmental based criteria.
As some quick example, a USER that has Authenticated to a Client Application that determines the user is a "Preferred Customer" vs a visitor might be granted scope to allow reading "Preferred Content".
The client then requests a "preferredcontent" scope for the "Preferred Customer" and not for the visitor.
And of course the Authorization Server may reject the scopes requested for any reason.

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.

Authenticate user with a unique temporary codewith IdentityServer4

I'm planning to bring in IdentityServer4 as a security token service to an existing solution. We can authenticate users with username/password pairs which covers majority of use cases we have.
However, we have some scenarios where small number of users are authenticated using a code emailed (embedded in a link, like www.mysite.com/codeusers/{uniquetempcode}) to the user, and given access to a limited section of the site.
Another, even less used scenario is to authenticate user based on their IP.
What is the best way to handle this kind of scenarios with IdentityServer4?
I don't know if this is the best way, but you can use Extension Grants for that:
OAuth 2.0 defines standard grant types for the token endpoint, such as
password, authorization_code and refresh_token. Extension grants are a
way to add support for non-standard token issuance scenarios like
token translation, delegation, or custom credentials.
http://docs.identityserver.io/en/latest/topics/extension_grants.html

API - allow users access to only data they created

This is an API related question that applies to the APIs that I'm working on and would like to know the standard way of doing this.
say a user1 has created accounts so he can access it by
GET /accounts
but when he accesses transactions for a particular account
GET /accounts/acct1/transactions
how would this API know that the acct1 actually belongs to that user1 and is not the case where user2 is accessing user1's accounts.
This api is accessed via a Mobile app using Oauth 2.0 tokens. So while the access token control the access to API endpoints, how do we control access to only specific user's data at that endpoint. (using scopes?)
I've been looking at Spotify's apis and they seem to be doing this via v1/me end point.. Still reading...
I'm a noob at this and it looks to me that this should be documented somewhere in a standard manner in some RFC, but I couldn't find it and would appreciate direction
Can you provide more details on your use case? Why are you using OAuth?
It sounds like you need an authentication protocol - i.e. a protocol to let your server know who is accessing a particular API.
To quote the OAuth website:
OAuth 2.0 is not an authentication protocol
OAuth's main use-case is letting one application perform operations on behalf of a user of another application.
As an example, if your server wants to post a message on Facebook on behalf of a user, you will use OAuth to obtain a token from Facebook which lets you post messages on behalf of the user. Note that, in the most general case, your application does not know which user is represented by the token. Indeed, the user may not even be a (registered) user of your application - they only have to be a user of Facebook.
Practically speaking, you often can use the token you have to query Facebook for the identity of the user. So your server would extract the OAuth token from the request headers and use it to issue a query to Facebook's Graph API to obtain the user ID.
Note that the user is a Facebook user rather than a user of your app, so you will need to somehow map the Facebook user ID to your own users and permission system - i.e. check your database to ensure that the user has permissions to do what they asked to do.
This is the mechanism that is typically used when using OAuth like an authentication protocol (which, as quoted above, it is not).
I should add that if your app obtains an OAuth token and passes it to your server for the purposes of authentication, then this flow is not 100% secure, as discussed for example here, so make sure you do proper risk analysis for your case. In a nutshell, a determined attacker can theoretically impersonate your app and obtain tokens representing other users.