API Authentication: Place the token in a cookie or a header? - ruby-on-rails

After having developed my first web portal (using railstutorial.org), I'm now making my way in building my first API (with some help).
Authentication for the web portal works with session as well as with a cookie (if the user wants his log in to be remembered).
For the API I understand that using session is insecure; you need to work only with a token. So, just as for the web portal, when a user logs into the API his credentials get checked, and if they are valid a token is generated of which the digest is stored to the database.
But then: I understand there are then three options what to do with the token: to store the token on the user's computer using a cookie, include the token as parameter or use the HTTP header. I read for APIs using the HTTP header is the preferred option.
If using the cookie, it is the same as the 'remember me' option for the web portal: the token is stored in the cookie and a digest of the token is stored in the database. With each API request the cookie is read and it is checked if it's token matches the digest.
Each time the API sends data to the user or the user makes a call to the API, the token is included as a parameter. I understand that this displays the token in the URL, which is not desirable.
My understanding of using the HTTP header fails.
What does it mean to use the HTTP header to send the token, instead of a cookie? What is the process/logic behind it? When to use a cookie, a parameter or the HTTP header?
Am I correct in my understanding that each time the API sends data to the user, it should include the token in the HTTP header? And each call the user makes to the API should include that same token?

I think this link is a good place to start : http://devcenter.kinvey.com/rest/guides/security
Also, reading up on some documentation of HttpAuthentication::Token should give you a basic overview of how/when you should utilize it.
http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html

You should look into how a cookie works. Setting a cookie is also sending a standardized http header to the client. When client sends a request, they can send cookie along with the request.
There is also a standard for http token in rails: Link Which is also setting a specific header in the request

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 OIDC, How/When to give JWT to the browser?

I'm implementing a SSO solution. Got a general question regarding authorization code flow grant type as described here.
After a user login, the client app would get an ID token. But I cannot find anywhere how/when a JWT should be given to the browser such that it can set the bearer token in the request header for any subsequent request? Is it something not specified in the standard or I misunderstand something?
The browser does not set the Authorization request header automatically. You have to do it yourself using Javascript. This means that a request with such a header must be an AJAX call. If you want to send regular requests through the browser (by navigating to a URL), then you have to use cookies, as they will be automatically added by the browser. (You can keep the value of a token in a cookie and have your backend read a cookie instead of the Authorization header)

What does `client` header value represents in devise_token_auth

I am trying to implement token based authorization in rails, with devise_token_auth (https://github.com/lynndylanhurley/devise_token_auth#conceptual).
When I post uid and password against sign_in method, it returns access-token, client (and uid itself) in header. I understand that token based authorization works like this:
User posts uid(id) and password to api server.
Api server validates the uid and password
Issues Token and returns it, if the uid and password matched.
Client receives the Token.
Client whenever client wants to access the authentication required apis, Client uses the uid and the Token in order to prove that this client is in fact already authenticated.
I can understand that access-token corresponds to the Token described in above explanation. That leads to me a question of what the client header value is, because it seems that, according to the official Wiki (https://github.com/lynndylanhurley/devise_token_auth#usage-tldr), devise_auth_token library not only use requires access-token but also client value.
Question:
In devise_token_auth, what is the purpose of client header value? Why is it also needed for identifying the user? Couldn't that be included in (or, concatenated to) the access-token value?
The client header is generated for every different device accessing the API. Its purpose is to maintain more than one session active for a specific user (web client, mobile client, etc.).
You can test this by signing in with the same user on 2 separate web clients and checking user.tokens, there should be 1 set of tokens for every client.

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.

Google+ Server Side Token Validation

I am using Google+ Sign-in in my application. A user gets an access_token back and I want to pass that token to my server and verify it with google. What is confusing me is conflicting information in google's documentation regarding the security of this:
https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken
Says I can make an ajax call with the access_token to check if it is a valid token. This works fine for me, however,
https://developers.google.com/+/web/signin/client-to-server-flow
Says never to send the access_token as a parameter in an http request to my server.
So, is it safe to use https://www.googleapis.com/oauth2/v1/tokeninfo or not?
There's a difference between sending the access token in an HTTP request to your server and sending it to Google's server.
When sending the access token to Google's tokeninfo endpoint for validation it's OK to send it as a query parameter, since it runs over HTTPs and Google is the issuer of the access token in the first place, so you're sending it to a known and controlled environment. Google assumes that Google knows what its doing.
But when sending the access token from client to your server (and you must make sure you use HTTPs anyhow) passing it as a query parameter is less secure since it may end up in logs and traffic analysis data on the server end. Examples of that are situations where there's a proxy in between client and server or you're using web hosting.
On top of that there are sophisticated attacks against OAuth 2.0 enabled systems that exploit the the fact that query parameters with tokens end up in Location and Referer headers. It is better to avoid the possibility of being exposed to any vulnerability like that. For a nice impression of those attacks, see http://www.oauthsecurity.com/ especially the section on open redirects.
I think the docs are saying to not use the access token as a GET parameter to your web app because most web servers will log the URLs accessed in an unprotected location unless it's specifically configured to not do it. So if you did an AJAX request to your backend server, the user's access token would be exposed in the web server logs.
Using the tokeninfo endpoint should be fine because Google does the logging and will handle the security of the logs. HTTPS protects the request URL and the message, so there are no special concerns using the access token as a GET parameter.

Resources