Passing user ID in body or in token - rest

I'm building a REST API. The API runs a JWT authentication system.
Obviously this means that paths that are secure need a valid JWT token to be passed along with the request in the Authorization Header. Inside each jwt token I have:
sub: 1 //_id
Where sub is the Id of the currently authenticated user.
My question is, when I pass this token, is there a need to pass the user id in the request body also? For instance, I have a create premises method. This requires a post body to contain a name and description like so:
{
name: "Test Premises",
description: "Lorem Ipsum"
}
In this case, the API would have to find the user to associate the new premises by verifying the token passed is valid, then unencoding it and retrieving the sub field.
Is this method ok?
are there any drawbacks?
should I be passing Id's in the body aswell?

is this method ok
Yes, that's the point of the authentication token.
should I be passing Id's in the body aswell?
You have a really big security hole if you allow the user ID to be sent from the client e.g. another authenticated user could create premises on behalf of another user if they knew (or spoofed) their ID.

Related

How to pass a parameter from a URL to an auth0 hook or rule for a machine-to-machine JWT?

I'd like to add a custom claim to a JSON web token generated by auth0 for machine-to-machine authentication. Like
color:blue
but I want to make blue a parameter I can pass with my request to auth0 for the token.
I ask for the token like this:
POST https://mydomain.eu.auth0.com/oauth/token
with a request body
{
"client_id":"myID",
"client_secret":"mySecret",
"audience" : "https://mydomain.eu.auth0.com/api/v2/",
"grant_type" :"client_credentials"
}
I see from How can I add claims to a JWT assigned with auth0 for a machine-to-machine application type? how to use a hook or rule to add a fixed claim, but I want to add a variable something like
?color=blue
to my request URL or request body and have that accessible from my hook code to be added as a claim.
Is that possible, please? How?
When you process an authorization request with a custom rule you get access to at least a part of the request properties by the request object of the context function argument. I tried it out but unfortunately the fields of the request object seem to be limited to only a few fields of the original request.
If your user information resides in Auth0 you could check out writing preferences into the user's metadata by using the Auth0 metadata API. This works well. But you will be able to only set metadata after the user has logged in, not before. Also you'll have to deal with two different Auth0 API endpoints now.

How to restrict a user to THEIR resources using JWT when there is no identity in the Access Token?

We have a REST resource like this:
/customer/{customerId}/bill
We want to use the JWT tokens returned from AWS Cognito to secure access to this resource.
The {customerId} here is not the Cognito user id, it's a domain specific id. We have added this domain specific id to the Cognito user as a custom attribute. It comes in the ID token that Cognito returns like this:
{
"sub": "xxxxxxxx-852f-474d-aa9e-a50fd832bcb8",
"aud": "xxxxxxxxsijed6uf54dh0uhi",
"custom:customerId": "4044",
"event_id": "xxxxxx-fc0c-4ffc-affa-f8987714fb2b",
"token_use": "id",
....
}
If we use this ID Token in Authorization: Bearer <ID Token> we can write code (custom authoriser or in-app code) that ensures the customerId in /customer/{customerId}/bill is equal to the value of custom:customerId in the supplied token, and we have secured our API.
But then we read that you should not use ID tokens to secure APIs . The key point being:
"The audience (the aud claim) of the (ID) token is set to the application's identifier, which means that only this specific application should consume this token."
So it seems we need to send an Access Token to secure the API. With Cognito, there is no way we can add any concept of who the user is into the Access Token. We can't add a custom scope like user:4044 for example.
What folks suggest as an approach here is to call the /userinfo endpoint of Cognito on the server-side with the supplied Access Token to learn who the user is. This would enable us to write code (custom authoriser or in-app code) that calls this endpoint and asserts permission. But it's an endpoint call for every request, which seems crazy.
One thought that crossed our minds was to use the Access Token to secure access to the API itself, but also require the ID token, either as a query parameter or a header to allow us do the fine grained access control. But that too starts to feel wrong.
Surely this is a solved problem? What is the right thing to do here?
Sorry, this question is a year old, so my answer is probably irrelevant. But for future wanderer, I would say that, given the limitations of cognito in allowing custom claims in the access token, a call to the /userinfo route is definitely the best way.
The API GATEWAY lets you cache authorizer response for a given user, so you won't be calling the endpoint on every request. Note that some implementations recommend it as a way to make sure that the token haven't been revoked.

How to prevent authenticated user from spoofing restful api calls

So I build a RESTful API. It has an /account/{id} endpoint to return user data. The API is secured via an identity server that issues the requester a JSON Web token (JWT) with access to the /account/{id} endpoint. The user sends a request with username and password and receives a JWT in return on successful authentication. Now the user sends a request for their account information to /account/{id}. The request is sent with a token in the header and returns a 200 response with the user data in the payload.
How would one go about authorizing the {id} in the endpoint? In other words, an authenticated user could just add any {id} in the endpoint and potentially receive another user's data. How is this prevented using the JWT?
You can store data in a web token. If you store the ID of the user, then you can identify them for each request they make. This is safe, because the contents of the token are signed with the private key of the server. Therefore their contents cannot be changed.
After that you can either limit the API so that each user can only query their own record, or you can also implement a complex role system, where each user has a set of roles (e.g. read-only, guest, maintainer, admin, client, etc.) that define which endpoints and how they can use.

Implementing own signup and login system for apps

I'm creating an app in which you are supposed to signup/login to use it. Now I'm implementing a restful webservice for it and I'm not sure whether I'm going the right way. My workflow is:
To signup, the user types in his credentials like username, email and password. The app hashes the password and sends a post request containing the credentials as json to my webservice and the webservice saves the new user to the database.
To login into the system, the app sends a get request including the parameters username and hash of the password to the webservice, compares the hash values and returns an appropriate response code for success oder fail.
The communication between app and webservice is secured by ssl.
Is this the right and secure workflow of a signup/login system? If not, why is it not secure and can you recommend another workflow? Cheers.
The most important part should be that your web service is only reachable via https.
I assume you are talking about a mobile app.
The app should not hash the password, the web service should do it and then store the user.
Mobile apps can be reverse engineered and then you know how to hash your passwords.
So to create a user in a restful way would be to send a POST request with username, email and password in the body.
For example POST /users
{
"username": "john-doe",
"email": "mail#example.org",
"password": "some password"
}
For authentication/authorization you might consider OAuth 2 but that takes a huge amount of time to implement.
Another option would be to have another REST resource called access-tokens.
So whenever you need to authenticate you do a POST /access-tokens request to create an access token.
POST /access-tokens
{
"username": "john-doe",
"password": "some password"
}
Response
{
"access_token": "9d91c97fc0f98a6311f101246e252ab3230c261c2af",
"expries_in": 3600
}
Then the mobile app needs to take care of that it will always create a new access token shortly before it expires. OAuth 2 has also refresh tokens for this purpose which are delivered together with the access token. Then you can retrieve a new access token just by sending the refresh token to the web service.
Once authenticated you need to include the access token in the Authorization header in every request to the web service that needs authentication.

How can I add claims to the context for GetProfileDataAsync & IsActiveAsync for a custom user service?

I am implementing a user service that is storing user info in Azure Table storage. I would like to use a value for tenant ID as part of my partition key, but, the claims available in GetProfileDataAsync and IsActiveAsync are just 5 built in claims (sub, name, amr, idp, auth_time).
I get tenant ID from my identity provider and it's included as a claim in both my access token & identity token. How can I make it available to those methods?
When the AuthenticateLocal is invoke, you return an AuthenticateResult to indicate the authentication outcome. If it's successful you use the ctor overload that accepts the subject and name values. There's also an optional claims collection. If you pass values for claims then you are adding your own custom claims to the authentication cookie at IdentityServer. Those claims are then part of the Subject for the GetProfile API (assuming the requests into those APIs are being done via the browser such as from the authorization request). You can then inspect those claims and use them in any way you want.
If the request is not via the browser, then the only claim you have on the Subject is the user's unique id (which is the sub claims).