JWT Token as source of User Details in an API? - spring-boot

I'm building out a backend REST API app, and it takes in requests from a client that uses Firebase Authentication, which will be passing in the JWT Token in the headers of all requests.
Should I still require UserID in the request body for requests, or should I just have the JWT Token be my source for decoding and fetching the UserID for all requests?
Using SpringBoot, and I think I can create a filter to decode the JWT for all requests and then create a User object that can be referenced throughout the chain.
But I'm not sure if it still makes sense to also require the UserID, if anything just as a point of documentation to say the UserID is being used here to handle business logic. Watcha think?

I don't think this would make any sense. You wouldn't actually use the value from the request body anywhere in the code, would you? Since your concern seems to be abobut documentation I'd rather clearly describe that resources in your application are bound to the authenticated user.

Related

Custom JWT token in springboot microservices

We have an application that loads information(user specific) from the external system upon successful authentication, to avoid round trips to the external system for each api call, we are planning create a custom JWT token with user specific information for the first time user authenticated, then the token is send to user in each response header using http interceptor and in the front-end we are including the custom token in every request along with authorization token. Is this correct approach? Do you have any alternative suggestions?
I have looked into other distributed caching techniques like redis but not so appealing for a small usecase. Our payload length does not exceed 4 to 5K hence inclined towards the JWT option
it is ok to include user information that allows you to handle the user authorization inside the access token. Just beware of the privacy implication and perhaps not include personal information like social security number or date-of-birth or other identifiable information.
Also, make sure the token size does not get to big. The other option is to lookup and cache the user information in the API's when it receives a new access token.
Some systems including ASP.NET Core do store the token inside the session cookie in an encrypted form, so that the end user can't see or access the stored tokens.
If you are developing a SPA application, the using the BFF pattern is one approach.

What to return after login via API?

I'm creating an API server which will be consumed by a mobile app that I will work on later. I have yet to see any reference of API best practices related to user flow and returned data even after searching for several hours.
My question is whether the login response of an API should return the a personal access token with the refresh token along with the user info? Or should I just return the token and make another API call for getting the user info.
I could just do what I have in mind but I'm trying to learn the best practices so that I don't have to adjust a lot of things later.
I need suggestions as well as good references related to my question.
Thank you.
It depends on what you are using for your authentication. If you are using libraries like Laravel Passport or JWT, you can have the token endpoint which returns the access token, refresh token, validity period and the token type (Bearer). You can then have an authenticated endpoint which will be used to get a user's profile based of the token passed in the request header.
However, if you go through the documentation for those libraries, in most there is an allowance to manually generate a token. You can use this in a custom endpoint that will return the token as well as the user profile Passport Manually Generate Token.
If you are using JWT, you can also embed a few user properties in the token itself. The client can the get the profile info from the JWT itself without having to make a round trip to the server. Passport ADD Profile to JWT
If you have a custom way in which you are handling authentication, you can pass the token as well as the user profile in the same response.
In the end, it's up to you to decide what suits you best.
Have you looked at OpenID Connect? It's another layer on top of OAuth 2.0 and provides user authentication (OAuth 2.0 does not cover authentication, it just assumes it happens) and ways to find information about the current user.
It has the concept of an ID_token, in addition to the OAuth access token, and also provides a /userinfo endpoint to retrieve information about the user.
You could put user information in your access token, but security best practice is to NOT allow your access token to be accessible from JavaScript (i.e. use HTTP_ONLY cookies to store your access token).

How should I load images if I use token-based authentication

I have a client-side application on domain client-domain.example and a server-side application on domain server-domain.example. There is an API on the server-side. The client-side application sends AJAX requests to the server-side application. I use token-based authentication, so the client-side application sends token in headers with each AJAX request, for example: "Authorization: Bearer {some token}". It works fine with AJAX requests, when I need to get or post some data.
But the server-side API also keeps files. For example images. The files are private, only authenticated users can get them. And I need to show this images on the client-side in <img> tag. I can't get them using <img src="http://server-domain.example/path/to/image"> because in this case browser will not send Authorization header to the server-side.
What is the adopted solution? How client applications load images from server-side API?
There are three methods to solve it, the best approach to solve it is using the signed URLs
1. signed URL (can be insecure)
The first method simply creates a route without authentication (anonymous access) with a signature hash parameter that indicates if the resource can be loaded or not.
<img src="http://server-domain.example/path/to/image?guid=f6fc84c9f21c24907d6bee6eec38cabab5fa9a7be8c4a7827fe9e56f2">
When the server receives the request it must validate the guid if the expiration time has not been reached and, of course, check if the guid has a valid signature.
This approach is used by several files/documents servers like Dropbox, S3, CDN providers, etc.
See the technique in some companies.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html#private-content-overview-choosing-duration
https://client.cdn77.example/support/knowledgebase/cdn-resource/how-do-i-set-up-signed-urls
SECURITY:
the guid can not be just UUID of the image/user, because this doesn't provide any protection.
the guid can not be the same token you use for authentication (for example, you can't use auth-JWT tokens), because the user can share the link - and the user will share his tokens (see also (2)).
as mentioned above: guid should have a server-side mechanism of validation (date/signature/...) and should not provide more permissions than "access to the requested file"
2 Query String with JWT (most probably a security breach)
The second method is to pass the token by querystring with the image URL.
This method is not recommendable because it exposes clearly the URL and many servers sometimes write and expose public logs of URL accessed. The bad notice is that the JWT exposed normally the user can get control a lot of features further the image load.
<img src="http://server-domain.example/path/to/image?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c">
When the server receives the request you must validate the token by querystring and response with the content.
SECURITY NOTES: worse than (1) - because now authentication info (JWT auth) is exposed in the URL and can be cached/logged by servers OR accessed by any server in the middle OR the user can simply share the "image link" with their colleagues.
But if JWT is NOT an access token, but a one-time token generated specifically for accessing that particular file in a form of JWT then it provides the same level of security as (1).
3. cookies
The third method creates an authenticated cookie to validate the access of the image.
This method is not recommendable because is out of API pattern (webapi/token based authentication in general).
When the server receives the request you need to validate if the validate cookie is valid.
SECURITY NOTES: if you can provide security for your cookies and XSS and CSRF — are not just letters for you then it is a solution. But keep in mind: cookies are sent by the browser automatically with each request. Much more information about possible threats and solutions: Where to store JWT in browser? How to protect against CSRF?
My solution to basically this exact same problem, based on Jeferson Tenorio's answer below (option 1), was to sign the URL to my API call with an encryption of the image and the user's JWT token, e.g. path/to/image?token=xxxx. In laravel this is easily accomplished with encrypt($your_object) and decrypt($token) (https://laravel.com/docs/5.7/encryption), and then I used the extracted token to verify the user had access to the file in question. But there are probably many other libraries capable of handling this.
I would be curious if there are any security concerns, but from my perspective the JWT is never exposed via plain text and the encryption relies on a secret key that malicious actors shouldn't have access to, so it seems like it should be fairly secure. My only real complaint is that the token is quite long using this method which does not make for presentable URLs.

Angular CSRF token + ruby api

I'm currently running into a lot of issues with the CSRF token.
Our current setup is a Ruby API and an Angular front-end, both live on a different domain.
The Ruby back-end solely serves as an API for the front-end.
I've spend a lot of time researching this problem, but I can't find a proper solution.
So far the solutions I've found are:
Generate the token and insert it into the DOM (Different domains, so can't do that)
Let the API return the CSRF token on a GET request (Doesn't seem to work, and it's not a good solution since I don't want to make an extra request just to get the token)
So I'm rather stuck here and not sure how to continue.
Is the current implementation just not working? How do other people create an API with oauth without running into this issue?
Not sure if this will help but here is a sample of a simple todo api in ruby with angular as frontend, and i am using token for authentication generated after the user fills username and password.
https://github.com/sirfilip/todoapi/blob/master/app.rb (the api written in sinatra and sequel)
https://github.com/sirfilip/todoapiclient/blob/master/public/js/angular-todoapi-plugin.js (angular client api service that is used for communication with the api)
TL;DR: Secure your rails API with the doorkeeper gem.
This SO post seems to be the accepted answer when your api and client exist on the same domain.
In the post they outline the angularJS docs http://docs.angularjs.org/api/ng.$http :
Since only JavaScript that runs on your domain could read the cookie,
your server can be assured that the XHR came from JavaScript running
on your domain.
To take advantage of this (CSRF Protection), your server needs to set
a token in a JavaScript readable session cookie called XSRF-TOKEN on
first HTTP GET request. On subsequent non-GET requests the server can
verify that the cookie matches X-XSRF-TOKEN HTTP header
It seems that the security of storing and transferring the XSRF-TOKEN session cookie in this way hinges on having your api and your front-end be in the same domain. Since this is not the case, you may have to implement another form of authorization for any given client session, like OAUTH. I'd recommend taking a look at the doorkeeper gem. The gem will give you the ability to interact with your api as if you were any other client.

Restful API: how to access the api securely?

I have just started reading on implementing RESTful web services and creating RESTful apis. I have understood the basic concept of REST but I have been scratching my head a bit on how I will implement it securely?
Say for example, my webapp has a user login process. After successfully logging in, what else should I pass in the RESTful request to authenticate on server???
What I can think of is the following process:
user logs in (POST username/password to API)
API responds with a userkey
userkey is stored locally
When making any further requests, I include this key in request be authenticated
But here it seems that userkey is a state which I am sending to API, but REST happens to be stateless. Also this is not too secure in case of sending GET requests.
Is OAUTH the solution to my dilemma? Or some other way? Can somebody guide me on this...
Thanks
UserKey, or better call it token, is a client-side state. Your RESTful API will remain stateless since it stores this token no where.
Usually this token is a combination of some segments (username, password, login date) hashed as MD5, SHA (or any other algorythm). Whenever client calls an operation of your RESTful API, your service will compare the incoming token with an on-the-fly generated one using the same segments. If both generated tokens are equal, request gets authenticated.
There's no problem with GET or POST methods: you'll need to retrieve your token from query string or an HTTP header.
The point to secure your connection is calling your RESTful API over SSL, so your communications will have a high degree of security.
An important problem with GET and sending this token using query strings is maybe it's too long and URL length limitations would prevent you from having a lot of arguments in addition to the token itself.
In my opinion, you should go with POST verb, because you can send more data, it's more flexible and you avoid giving problematic arguments in query string, which can be bad in terms of logging, since you're going to log user names, passwords, tokens and other things, which are sensitive information that can compromise your users if a hacker steals your logs (or some unwanted person checks your log too).
OAuth is stateless - it's a token that proves that someone has authorized a client to do something - like a drivers license where the government has authorized a citizen to drive around in a car on their streets.
So - yes - use OAuth.

Resources