Correct workflow of a REST API for mobile app authentication - rest

I am in the process of building a REST API for mobile app developers to be used on a web application built using Zend framework. My first task is to create a service for authentication/authorization. I have read lots of related questions here on SO and would like to sum up what I am doing:
There is no session or cookie involved, so a typical web app method
of checking the logged in state of the user doesn't work here.
With each login request, the username and password is received and a
random string is generated and saved in the DB against the username.
Also, this string is returned with the authentication request.
This user token is sent along with any request that needs authentication.This token is matched against the stored value in DB and if matched, only then the user is allowed to perform the required task.
On logout, the token value in the DB is reset to blank or NULL.
Is this the correct approach ? Won't it over load the DB because with each request, a select query is run on the DB to check for the token value ? If you could provide any tutorial link, that'd be much appreciated.

Related

Authentication Practices with Node Express

I built a simple authentication system for my backend API with Express using Cookie-Parser and/or sending the Token to the front end.
It works like this: the user makes a post request to the login route with the username and password, and if it matches, he gets back both a .json response with the token and a cookie set with the token.
I thought it would be nice for the frontend development and authorization purposes to have the current user available in every successive request after the login. So, I set a middleware that searches if there is a token, tries to find a user in database with the corresponding ID, and set the user info (without the password) as a parameter in the request object (req.user).
What I wanted to know is:
Is it a bad practice to put the user info in the request? Does it lead to security problems? Or maybe the database query in every request could overload the server if the app scales to much?
This is my first backend API, I'm trying out different ways of doing things, but I'm not aware of the best practices in the field. Any help is very much appreciated!
That is why there is encryption and in this context it is an ssl ticket. If you add login details to the request you NEED to make sure that the http response is encrypted. Once it is encrypted it is ok to do what you are doing. If it is not, an eaves dropper can snatch up that data from sniffing on your network.

Call REST API with and without user context

I have a user microservice. This microservice uses token authorization. Now it's consumed by web application. Workflow looks like this:
user logs in to web application using AzureAd OpenIdConnect;
web application receives access token (authorization code flow);
web application gets user details from user service passing access token in HTTP request header.
Also I have a daemon microservice where I don't have a user context. I want to allow this daemon service to get user details from user service too. I'm going to use client credentials flow for that case.
How to organize user service rest api properly?
I'm thinking about this approach:
user's data is available at this URL /users/{userId}/info;
applications with user context (i.e. access token is issued for particular user using authorization code flow) can consume data only for current user or current user is an admin and can work with another user's data;
daemon applications without current user (i.e. access token is issued for the application itself using client credentials flow) can read data for any user.
What is the best practices for such cases?
I think the best and more restful approach to define this API is to build a unique endpoint /users/{id}.
Where id can be an actual real user id or a predefined value like 'me'. It is the user service the one who has to retrieve from the token the user information in case that the id value is 'me'.
The other changes that I would make is to use users instead of user because rest good practices say that the elements in the URL are collection.
And the last one, to not use info because it is redundant. Because when you query for an entity obviously you want its info

Limit user access to api calls?

I am creating a rest api to be the backend for a messaging app. I want a user to only have access to their own data. For example user1 can call /users/user1 but not /users/user2. How would I go about doing this.
So first the user will login and be authenticated via their username and password. But where do I go from here? I was thinking of storing a token with the users data so when they access it I can verify that the pair matches but there must be a better way to do this. Do I need to restructure my api?
After the user logs into the system, you should provide them a token or initialize a session for that user. In each consecutive call, the user should send the token to the API. As long as the token/session is alive user should be able to call the API.
You should have a way to verify the user token in the backend for each API call. A very popular way of doing this is to use JWT(JSON Web Tokens) based authentication.
See here for an example using python and flask: https://realpython.com/token-based-authentication-with-flask/
Once you verify the user, you should parse the user id to the database query in order to filter out the data for that user.
Even though I don't understand your full use case, it seems like you need to restructure your API calls as well. You should not provide API calls per user. What happens when the numbers of users increase in your system dynamically?
So you should either accept user id as a parameter or you should let the JWT authenticator take care of it.
Example REST API call would be
GET /user/data?userId=1234

OAuth - what to store on disk

TL;DR When using google oauth on desktop app, what to save on disk to avoid repeated sign in? Save the google user id? or the token? or an session id?
I'm creating an little desktop app, whitch must authenticate to my REST API server. I'm using google oauth2 for that.
The idea is, that when the desktop app will be authentivated, it generates some data that will be send to my server. The server will store the data with the google user id received from https://www.googleapis.com/userinfo/v2/me.
On the first run of the desktop app, it will open the default browser, with and url for my server and start an local http server. then:
my server will redirect the browser to google (with the clientid, secret, etc.)
user logs in and it will be redirected back to the server with the oauth code
server uses the code to get the token, and then the user profile and stores the token and the profile in db, then redirects the browser to localhost with an paramerer
the desktop app catches the parameter and stores it in an file on the disk
next time the desktop app will start it only reads the file for the parameter to send the generated data with it to my server
my question is: what the parameter should be? the google user id? the oauth token? an generated session id for this desktop app? or something else?
when it will be the google user id, it can conveniently sent the data with the user id and the rest server will just store it in db as is. but I don't think it's safe
when it will be the token, the rest server has to with every request also get the user profile from google with the token. and imho sending the token with every request isn't safe either
generating an session id means to store it with the user and the token on the server and the desktop app will just store it and send it with every request. but I don't know if it's safe to do that
As it's normally the case in software development you have a couple of options depending on requirements.
The mandatory requirement is that your client (desktop) application needs to send something to your REST API so that the API can perform up to two decisions:
Decide who the user is.
Decide if the user is authorized to perform the currently requested action.
The second step may not be applicable if all authenticated users have access to exactly the same set of actions so I'll cover both scenarios.
Also note that, for the first step, sending the Google user ID is not a valid option as that information can be obtained by other parties and does not ensure that the user did authenticate to use your application.
Option 1 - Authentication without fine-grained authorization
Either always sending the id_token or exchanging that token with your custom session identifier both meet the previous requirement, because the id_token contains an audience that clearly indicates the user authenticated to use your application and the session identifier is generated by your application so it can also ensure that. The requests to your API need to use HTTPS, otherwise it will be too easy for the token or session ID to be captured by an attacker.
If you go with the id_token alternative you need to take in consideration that the token will expire; for this, a few options again:
repeat the authentication process another time; if the user still has a session it will indeed be quicker, but you still have to open a browser, local server and repeat the whole steps.
request offline_access when doing the first authentication.
With the last option you should get a refresh token that would allow for your application to have a way to identify the user even after the first id_token expires. I say should, because Google seems to do things a bit different than the specification, for example, the way to obtain the refresh token is by providing access_type=offline instead of the offline_access from OpenID Connect.
Personally, I would go with the session identifier as you'll have more control over lifetime and it may also be simpler.
Option 2 - Authentication + fine-grained authorization
If you need a fine-grained authorization system for your REST API then the best approach would be to authenticate your users with Google, but then have an OAuth 2.0 compliant authorization server that would issue access tokens specific for your API.
For the authorization server implementation, you could either:
Implement it yourself or leverage open source components
⤷ may be time consuming, complex and mitigation of security risks would all fall on you
Use a third-party OAuth 2.0 as a servive authorization provider like Auth0
⤷ easy to get started, depending on amount of usage (the free plan on Auth0 goes up to 7000 users) it will cost you money instead of time
Disclosure: I work at Auth0.
There should be no problem sending the access_token with every request since they are created for that purpose and are thus short lived. You can use the Google Authorization Server endpoint to verify a token instead of using it to do a request for a users profile.
If you're only relying on Google for authentication, here's how your workflow can look:
the client (desktop application, in your case) retrieves the
Google id_token following the user's log in, and then sends it to
the server
the server validates the integrity of said token and extracts the user's profile data; this could mean a simple GET on Google's endpoint to verify this token: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
On subsequent requests, nothing should change really, except that the user's login process will be automated (since he's given permissions & all), and thus much faster. #danielx is right, there's no problem with sending the token each and every time.

Spring boot REST token authorization and authentication best practices

What is the best practise for authorization and authentication of users in REST spring boot?
I am building web app with standard pages + REST API for mobile. I looked at many articles about Spring security and basically most of them goes with some sort of fitler approach that will allow or block REST calls. In my case, however, I have some auth logic based on who the user is. For example, there is a /update API that updates user information, and user can update himself, but cannot update other person.
Initially I thought to use next auth schema:
User calls auth API and pass name/password or cookie
System generates short life token, saves in it's database.
User get this token, updates his cookie (so JS in web application can read and use it)
When REST call is being make cookies are passed. At Controller, token is extracted, checked for expiration, query is done to database to validate token and get user id.
Based on user id, REST will be permited or blocked.
Is this the right approach to implement? I have a pretty big mess in my head after reading articles about spring boot security.
At least: session auth will not work for me (REST is stateless). I want to make auth for mobile device without storing login/password there.
Does it make sense to pass this token in the REST body itself? What in case of GET method?
Many thanks for sharing your knowledge.
Did you find a solution to your problem?
I have answered this problem elsewhere, if you are sure you won't want to open up the API to other developers/clients in the future (if you do then you should look at OAuth) then a simple token based solution will work.
Something basically along the lines of this:
Setup a standard html login page, that you can use for user login to the app
setup spring security to return a cookie on sucessful login with an authentication token
in your mobile app, embed a WebView (or equivalent) and load this login form - allow the user to login via that webview, on response grab the cookie and store the token (as mobile is generally single user, you can keep that pretty long to save mobile users having to keep logging in)
Add a security filter to the the REST API to authenticate against the token (from the mobile app pass the token in the header for example) - then you will be able to use normal spring authentication context for current users etc.
This approach is suggested by Google here: (EDIT: Google seems to have changed the page I originally read to be about using Google+ sign in and OAuth2.0 - I can't see a link to their general Mobile/API docs so here it is in the web archive :) )
I have also written up my implementation here:
Overview of the approach using Spring security
The code & details
Although this was really just an experiment/Proof of concept, it might be useful in your thinking.
Cookie approach seems perfect for the use case. Token can be tied up with user id. Filter can extract cookie and pass user id for example as header to apis - that should take care of GET...