Token-based authentication from a mobile app - ios

I am learning about Token-based authentication with JSON Web Tokens and here is how I see it now for a mobile app, built with, e.g. Swift:
I can create an object inside the app using user input, like
{
username: "patrickbateman",
password: "ismyknifesharp",
role: "regular",
...
}
Then I can generate a JWT token from it with a library.
Then I send it to a supported API endpoint, like /api/contacts/list. Or do I have to send login/password as they are to authenticate?
Server somehow checks the token correctness. But how? Should this server-generated token be saved in the database and used as a key? Or do I have to generate the token on server each time I get a request from client and compare it to client token?
Get and manage all the data I need.
Here are my conclusions:
I don't need to send login/password pair to server to authenticate the user.
I need to send token each time I need to get auth-only data.
I should implement some algorithm that changes the generated token due to some factors, like time passing, so that to make tokens expirable.
I should send the token inside headers, but not necessarily, as it can be done inside the body of the JSON requests.
Are these conclusions correct? What's the way to check token that client sends?

My opinions:
We should not keep password of user on client. Client should post password to server when sign up/ sign in, and don't save it anywhere in client. Request should be https, and password should not be encrypted. We will encrypt password later at server side.
Server will generate a token for this user after user login successfully. The token will contain the expired date in itself. We will use the token to authenticate permission with server.
I think every request to API should provide the token, except the sign up / sign in/ forgot password requests.
Token should be put inside the header of request.
Server should allow client request a new token with the old token (maybe be expired)
And the answer for "How to server check the token from client?". There are many ways to do that. The way below is my current approach:
Server side generate a token, which is a encrypted string of a user info (such as token expired time, userid, role... of user) and a password (keep only on server side) with HMAC or RSA algorithms. When user submit a token, server can decrypt and get the user info, expired time without querying from database.
Anyway, this question does not relate with Swift tag.

Related

Best way to store code_challenge and code_challenge_method in OAuth2(PKCE flow)

OAuth2(PKCE flow)
A client app makes a call to /authorize endpoint of the authorization server with code_challenge and code_challenge_method. Both code_challenge and code_challenge_method are required in the subsequent requests of the authorization server along with user credentials to generate the authorization code.
I can think of 2 options for how to store code_challenge and code_challenge_method to use in the subsequent calls:
persist the code_challenge and code_challenge_method before redirecting to the login page or user consent page
pass the code_challenge and code_challenge_method to the login page in query parameters, those then will be submitted along with the credentials
As RFC does not talk about this much, which option is better and why, or are there any other options? Please suggest.
Also, are there any best design practices about authorization server endpoints(except /authorize and /token) implementations in OAuth2(PKCE flow)?
According to Add Login Using the Authorization Code Flow with PKCE
There are 2 codes when doing PKCE :
Code verifier, the random string
Code challenger, the hashed string from the code verifier, and his hash method, the code_challenge_method
In the Oauth2 authorization_code flow, a client needs 2 tokens:
authorization token, to request accessToken
accessToken, to access resources
To get the authorization token with PKCE, a client app will have to pass the code challenger & method in the URL parameter, then the user is redirected to login page.
After login, the authorization server redirect user back to the client app, with authorization token in url parameters.
Finally the client app request access token with authorization token, code verifier, client id, and all other parameters.
When the ressources server receive the request for access token, it has to "remember" which code challenge to use to test with the code verifier.
Suppose there are 1000 users authorizing in the same time, there will be 1000 authorizations & code challengers per app client id.
The authorization server should accurately find the right user (authorization & code challenge) along the 1000 users to verify the code & generate access code.
I think this answers your question, storing code challenge after user login, which means pass it to login page (but encrypted, because there is a code challenge methode named plain...)
I don't see how we can link the user & code challenge when the authorization server first receive the authorization request.
RFC 7636 Section 4.4 states (emphasis mine):
Typically, the "code_challenge" and "code_challenge_method" values
are stored in encrypted form in the "code" itself but could
alternatively be stored on the server associated with the code. The
server MUST NOT include the "code_challenge" value in client requests
in a form that other entities can extract.
This rules out your option 2, as the challenge would be available in plain text to the user agent. It does however specify another option to encode this information into the code value, but it seems like this is not what you're looking for.
You're looking for a way to store the challenge while redirecting the user to the login page, before generating the code. In this case you could store the challenge in an encrypted httpOnly cookie in order to maintain a stateless design. A successful login would redirect the user agent back to your /authorize endpoint where you can extract the cookie again and generate the authorization response.

Oauth2: is the refresh token limited to the app that generated it or not?

If i've an application, and I use its app_id and app_secret to login and get an access_token and a refresh_token back.
The refresh_token can be used by any application or just by the one that created it?
Similarly, if the app is public (it does not require the usage of app_secret) is still the refresh_token linked to the application or can it be freely used by any other app?
A refresh token is associated to a client (and also to a specific user when applicable). Typically the Authorization Server will store details such as client_id, sub, refresh token hash, expiry and revocation status in a database table called something like delegations.
When a client sends a refresh token grant message, the client_id must also be sent:
For public clients, anyone who can get hold of a refresh token can send the request
For confidential clients, a client secret must also be provided. This can be a string value or a stronger credential, such as a client certificate.
In both cases the Authorization Server will typically use the received details to find the database row, return an error if the token is expired, revoked etc, or otherwise return a fresh access token. This article provides a good overview with sone further info.

How to validate CSRF tokens?

I'm trying to use the Hapi's plugin Crumb to implement a solution againts CSRF attacks, but seems that I didn't get the solution flow.
I could simply set a token in each http response as a cookie. And here comes the question, how REST can validate CSRF token, if token issued by client? How REST backend understand what this random string is valid for this request and another random string is not?
It's not possible to generate CSRF token on the client. It should be send from server to client first, and some JS frameworks extract it automatically from the cookie and send it to the server.
The basic idea is that user is supposed to send token along with a cookie and also in the post data. Here is a simple example. If attacker will trick a user to send a particular request to a service, for instance malicious website can have an image with this link src="gmail.com/deleteaccount=true". If user is logged in to gmail. Gmail will think that it was a user who made the request, because cookie send along with request is valid. So, in order to make sure that it was actually a user, gmail also requires a token send with a request data: so instead of gmail.com/deleteaccount=true it needs gmail.com/deleteaccount=true&token=987y23459827345sdfg. Token have to match the one stored in the cookie. So when request is received by a server, it checks if token in the cookie equals to token in the request body. Attacker have no access to user's cookies and don't know the token.
Here is the simplified data flow:
In more details it looks like this:
1) User sends GET request to a server
2) Server sets the cookie with
sessionid, and saving session data with the token
3) server returns HTML with a form containing token in a hidden field.
4) User submits
form, along with a hidden field
5) server compares token from the
submitted form (hidden field) with the token saved in the session storage. If they match, it means that form is submitted by a user.
Here is another grate answer: Why is it common to put CSRF prevention tokens in cookies?

OpenId Connect Questions -Authorization Code Flow (OAuth 2.0)

I am facing a custom implementation of OpenId Connect. But (there is always a but) I have some doubts:
I understand the process of obtainning an acces_token an a id_token, except the step when the OP provides an authorization_code to the client. If it is done by a redirect (using the redirect uri)
HTTP/1.1 302 Found
Location: https://client.example.org/cb?
code=SplxlOBeZQQYbYS6WxSbIA
&state=af0ifjsldkj
The end-user is able to see that authorization code? It does not expire? Imagine we catch it and we use later (some days later) Is it a security hole? Should the state be expired in the Token Endpoint?
The flow continues and we got at the client the Access_token and the id_token in the client.
How the Access_token should be used on the OP side ? It should be stored in a database? Or be self containing of the information required to validate it ?What would you recommend?
And in the client-side , both tokens should be sent in every request?
And the last doubt, if we have an Access_token the existence of an id_token is for representing authorization and authentication in separated tokens?
Extra doubts:
I know the process to obtain an access token but I have doubts of how the OP ,once generated and sent, it validates the access_token that comes with every request
How the OP knows an access token is valid? As far as I know, the OP should say that an access_token is valid/invalid. There should be some way to check it right? How it gets to know that a token represents a valid authenticated user if it is not stored in DB?
Is it a bad idea to store access_token in a cookie? Because sometimes we call to some webservices and we want to send access_token as parameter. Or there is another workaroundsolution?
How the access token should be stored in the Client , for example, in ASP.NET, in the session?
Thanks very much to all of you, I will give upvote and mark as answer as soon as you give me the explanations.
Thanks!
The end-user is able to see that authorization code?
Yes. Although, even if the authorization code can be seen, the token request requires that the client's secret be sent as well (which the browser does not see)
it does not expires? Imagine we catch it and we use later (some days later) It is a security hole? Should the state be expired in the Token Endpoint?
The spec says that the authorization code should expire. See https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.
How the Access_token should be used on the OP side ? It should be stored in a database? Or be self containing of the information required to validate it ?What would you recommend?
The access token should be stored on the OP if you want to be able to revoke the tokens. If you don't, the token will be in JWT format (self-contained)...but you should store it if you want to be able to revoke it whether it's a JWT or not.
And in the client-side , both tokens should be sent in every request?
No, just the access token.
And the last doubt, if we have an Access_token the existance of an id_token is for representing authorization and authentication in separeted tokens?
Yes, they are separate tokens for different purposes. Access token is for authorization and Id token is self contained and used to communicate to the client that the user is authenticated.
How the OP knows an access token is valid? As far as i know, the OP should say that an access_token is valid/invalid. There should be some way to check it right? How it gets to know that a token represents a valid authenticated user if it is not stored in DB?
see How to validate an OAuth 2.0 access token for a resource server? about thoughts on how the resource server should validate the access token before letting the request from the client go through.
It´s a bad idea to store access_token in a cookie? because sometimes we call to some webservices and we want to send access_token as parameter. Or there is another workaroundsolution?
I'm assuming you're using the authorization code grant flow (...from your questions). If that's the case, the reason why an authorization code is, first of all, passed back from the OP rather than the access token is so that the access token can stay hidden on the server side--away from the browser itself. With the authorization code grant flow, the access token should stay out of the browser. If you're wanting to send api requests to the resource server directly from the browser, then look into the oauth2 implicit flow (https://www.rfc-editor.org/rfc/rfc6749#section-4.2).
How the access token should be stored in the Client , for example, in ASP.NET, in the session?
In the OpenID Connect flavour of OAuth2, the access token is for offline_access (i.e. outside of an authenticated "session"). The access token could be used during the session of the user but it might be better to store the refresh token in the database so that your client app can request new access tokens whenever it needs to and as long as the refresh token is valid...even when the user's authentication is expired. The access token should be short-lived so storing it in the database is an option but not necessary.

REST API: Do I need to authenticate log out action?

I'm writing a REST API server(using Rails), and here is a question about session management.
I think for a REST API server, we don't need to save the log in state(or session) for each user. So I just add an authentication token for each user. If they log in, this server will return this token to them, and if log out, destroy it.
And I'm wondering if it's necessary to authenticate this token destroy action? There might be a malicious user who iterate all possible tokens(maybe!) and wrap them in a DELETE request to my server...
Thanks a lot!
One of the aspects of restful web services is statelessness as described in the Wikipedia article.
The client–server communication is further constrained by no client context being stored on the server between requests. Each request from any client contains all the information necessary to service the request, and session state is held in the client.
The server should not contain any information about sessions, that means, that the authentication information must be contained in each request and no login or logout methods are needed.
Best practice would be providing a resource (like some OAuth2 implementations), that returns a token with a special scope and an expiration time. At the creating process, the token should be stored in the database of the backend. After the token expires, the information must be deleted from the database and the client has to obtain a new copy of the token.
UPDATE:
#Ekkehard, that's exactly what I meant with my comment. Instead of using ‚stateful' http sessions with a session id, cookies and a session timeout, the token should be provided by an additional resource.
[...] no client context being stored on the server between requests.
If the client wants to access special services of the backend, it had to send a POST request to the token resource (where the backend stores the new token with a special expiration time in the database).
In the POST request, the client could also provide an additional query parameter scope, to create a token, that only allows you to access special parts of your backend (Google for example provides many different APIs like Google Drive, Google Mail, etc. and if the client is a mail application only access to Google Mail is necessary. It’s an additional security feature.).
The response returns the token and the client had to add this token in the header of each request to other resources.
Each request from any client contains all the information necessary to service the request, and session state is held in the client.
The tokens will be verified from the backend based on the information stored in the database.
Token resources could also provide a DELETE http method, to allow the user to delete existing tokens before the end of the expiration time. After the expiration timeout, the tokens will be automatically deleted from the database of the backend.
You can use authentication token for API. Concept is simple if your username and password matched you just create a token and send to user.
You need to set a expiration time for this token.
After expiration time or when API request for destroy you just delete this token.
Token must be send with each request.
In this approach you don't need any session.
RESTful applications must be stateless and the security tokens need to be sent within each request using the header Authorization. Such security tokens are gotten from an authorization server using credentials or using OAuth2 authentication flow (see this link for more details http://www.bubblecode.net/en/2013/03/10/understanding-oauth2/). Such tokens have expiration dates or can be invalidated from this server.
This link could also you give more hints about the way to use tokens within RESTful applications:
Implementing authentication with tokens for RESTful applications: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
Hope it helps you,
Thierry
If someone knows your token then they can use it to authenticate as you. In other words, by sending the token in to delete, you are authenticating yourself. No additional credentials beyond the token should be needed in a DELETE action.
There are simply too many possible tokens to iterate over for this to be a plausible attack. The attack you are worrying about is not unique to DELETE. If a user could iterate over all tokens then they would be able to impersonate any user for any action.
Simple answer is: YES, you need to authenticate this token destroy action
Here is three things:
If username and password matches user get a token. You need to set a expiration time for this token.
User must have to send token in each request. So, no session in server side is necessary.
If user want to logout, destroy the token from client side, and reset token in server side. And also authenticate this token destroy action
Note: destroy the token after expiration time.
Another Note: Devise gem reset the remember_token, when we logout from web UI.

Resources