Is it bad to have access token in OAuth redirect URL - rest

I am building an oauth login flow and I am not sure if I have done it wrong because I will need to send the bearer token back via redirect URL, like /oauth2/redirect?token=[TOKEN]. But isn't it not recommended to have token passed along through URL? As it is pointed out in this thread:
Don't pass bearer tokens in page URLs: Bearer tokens SHOULD NOT be passed in page URLs (for example, as query string parameters).Instead, bearer tokens SHOULD be passed in HTTP message headers or message bodies for which confidentiality measures are taken. Browsers, web servers, and other software may not adequately secure URLs in the browser history, web server logs, and other data structures. If bearer tokens are passed in page URLs, attackers might be able to steal them from the history data, logs, or other unsecured locations.
I must have missed something in the whole flow and would like to understand more about this matter. Any input is appreciated!
UPDATE
Might not be correct but this is my understanding after some digging. The three means to pass token:
URL (not preferable)
Auth header
Request body
But under the oauth redirect use case, option 2 and 3 not feasible. So option 1 is the only option available. If really needed, token can be encrypted to ensure security.

I think this only means, that you should not use a GET request when the server requires the token, instead you should use POST or whatever is appropriate. In a GET request the parameters are included in the URL and those can end up in logs or other histories, other request types will send the paramters separat from the request URL.
P.S. BTW if you are not implementing the OAuth server yourself, you won't have to send a redirect url containing the token.

The basic auth header which provides a little extra security as it's required to be through TLS:
In the case of a "Basic" authentication like shown in the figure, the exchange must happen over an HTTPS (TLS) connection to be secure.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
Also, the headers aren't logged in easy places like browser history.
From the spec,
it SHOULD NOT be used
unless it is impossible to transport the access token in the
"Authorization" request header field or the HTTP request entity-body.
https://www.rfc-editor.org/rfc/rfc6750#section-2.3

Related

Do I need CSRF protection for /login endpoint?

I know
this question has already been asked so many times, but after hours of searching I still don't have a clear answer to my problem.
Even projects like https://github.com/pillarjs/understanding-csrf have been abandoned and have not answered to new questions and doubts over the years like this.
PROBLEM
Let's say I have:
a back-end on back.domain.com and
a front-end on front.domain.com.
My back-end is a simply nodejs app with these rest endpoints:
POST /login:
accepts JSON body like: {"username": "myname", "password": "mypass"}
verify credentials
if OK gives 200 and create a cookie with session
if NOT gives 401
GET /players:
check session in cookie
if OK gives 200 with {"players": "[...]"}
if NOT gives 401
POST /player/1:
check session in cookie
if OK gives 200 and edit player
if NOT gives 401
My front-end app has:
/login page with a form (with username and password fields) for issue a POST request to back.domain.com/login
/players which request a GET request to back.domain.com/players
a button which issues a POST request to back.domain.com/player/1
QUESTIONS
Do I need CSRF protection in this scenario?
I think YES, I need because an attacker can issue a request to back.domain.com/player/1 from malicious.site.com and use my session cookie to edit player because I'm logged in (and I still have a session cookie) on my domain.com.
Do I need CSRF protection (e.g. an X-CSRF-Token header) when I the first time login on back.domain.com/login?
In this scenario I still don't have any session cookie in my browser.
And also I don't know where to get my CSRF token for X-CSRF-Token authorization header too.
I read on https://fractalideas.com/blog/making-react-and-django-play-well-together-single-page-app-model they are creating a dedicated endpoint on back-end for this and they explain it's not a security vulnerability.
What do you think about?
You are correct.
You DO need CSRF protection any time BOTH of the following are true:
the browser is automatically providing the authentication mechanism (most common way this is done is with a cookie)
the operation is state-changing on your backend
Of your three endpoints, only one meets both of those conditions.
GET /players/: get is not a state-changing operation. No CSRF protection needed.
POST /player/1/: authentication provided by cookie; post is state-changing. Needs CSRF protection!
POST /login/: the browser is not automatically providing the authentication information; it’s coming from data the user has intentionally typed in and submitted. No CSRF protection needed.
You’ll find other schools of thought - this other stack overflow post indicates the possibility of privacy-violation attacks, but the method described stretches credulity a bit in my opinion. And in any case you are right - if your frontend and backend are being served by totally different servers, your frontend won’t have the CSRF token before the user logs in.

OAuth2 security in REST GET API

I understand that OAuth2 is a good way to secure access to a REST API. I also understand that unlike in a simple website or in a SOAP API, in a REST API you want to use the right HTTP method for the right task. That is GET to read data, POST to write, etc.
My question is, when doing a GET call to a REST API secured via OAuth2, how do you protect your access token ? I don't see any other way to pass it to the server than in clear view in the URL, so isn't it that anybody that can see my call on the network could hijack my authorization ?
A HTTP request has a couple of major components:
The method
The url
Headers
Body
The OAuth2 Bearer token is usually sent in the headers, as such:
GET /thingy HTTP/1.1
Host: api.example.org
Authorization: Bearer [secret]
As an aside, this assumption is not really correct either:
so isn't it that anybody that can see my call on the network could hijack my authorization ?
If you don't use HTTPS, anyone can still see this token even if it's in a header. If you do use HTTPS, putting a token in the url shouldn't allow anyone else to snoop. However, putting secrets in urls is considered a bad practice for different reasons. Specifically, people don't like it because the tokens can end up in a browsers history and in logs. This increases the chances of it accidentally falling in the wrong hands.

Authentication on RESTful API on GET requests

So REST architecture implements GET, POST, PUT and DELETE requests. I would like to talk about GET requests. http://example.com/api/students this is a GET request under the REST architecture that will give me a list of students in the database.
My question is about authentication. it seems the best way to authenticate on a GET request would be by using an Access Token, like http://example.com/api/students?token=randomstring
How is this handled serverside, I mean a secuencial process, to prevent somebody from stealing another user's access token and using it. Is the token refreshed on every request and returned along the results or something like that?
First of all - you should never put credentials (access tokens) in URLs. Its not exactly wrong or prohibited per se - its just bad practice since it makes it impossible to share URLs without exposing secret credentials (think about what would happen if you copied the URL into an e-mail and send it to a friend). Credentials in URLs simply makes it too easy to accidentally expose them to others.
Take the token and stuff it into the HTTP Authorization header instead - that's why we have it. There are many different ways to use that header, but in your case you would want to use the "bearer" token method. Here is an example from the RFC (https://www.rfc-editor.org/rfc/rfc6750):
GET /api/students HTTP/1.1
Host: example.com
Authorization: Bearer rAndomSTRiNg
On the server you check the validity of the token before doing anything else. To prevent others from stealing it you enforce SSL/TLS on the connection.
The token may need to be refreshed - but that depends on how you obtained it and the rest of your infrastructure. Usually you do not need to refresh it for every request - only after a certain time when it is expired.
You may want to look at OAuth2 which defines four basic ways of obtaining access tokens.

Tracking consumers for RESTful API (no auth)

Folks,
What is a simplest way to track consumer applications accessing RESTful API services inside department.
We do not restrict access - no authentication/authorization - open for invocation, trusted environment.
No tools like OAuth AuthZ servers or API management yet... but might be heading there at some point.
For now we thought to request consumers just to include some custom HTTP Header like X-Client-Id and log it on the server side for stats etc..
But knowing that in the future we might want to switch to more standard ways of doing things ... what would be best alternative to have to change less code in the future ?
Have the "clientId" in the Authorization: OAuth token (like access token)
Have JWT token in the Authorization header (looks too much - signing,base 64 etc for simple client id tracking ...)
Any ideas would be appreciated
We recently implemented this for one of our REST platforms and we used a combination of BOTH the points you mentioned, meaning Authorization header & JWT token. Although, JWT is ONLY for authentication and GETTING an access_token (oauth token) which is later used with calling actual resource apis. I will discuss how we handled this situation and you can decide on how you want to implement it.
1) Authentication
Client sends a JWT to your authentication service (/api/oauth2/auth). (If you want more reading on JWT, you can read here and here of how JWT is implemented by google and how you can use spring-security-jwt libary to handle all the signing and encrypting/decrypting). You get the "clientId" out of JWT after decrypting and verifying the signature and after server does all the authentication, you respond back with a 'refresh_token' and an 'access_token'. Server will save the access_token as well and map it to the clientId so that when client makes requests using access_token, you can know which client is making the request. The access_token expires in some time (ideally in an hour) and when it expires, the client uses the 'refresh_token' to get a new access token by posting refresh_token to some refresh token url (/api/oauth2/auth/token)
2) Authorization
Client takes the 'access_token' and uses the access token to make all the subsequent requests on all other apis (/api/*). Ideally, the access_token is sent as a part of the "Authorization" header. Server uses request filters (if you are using JAX-RS, you can use something like ContainerFilterRequest to add filters to specific url patterns and intercept them) to filter EACH request and parse out the Authorization header value. You will get the access_token from the header and from the access_token you can get the clientId that you mapped in step 1). You can do other authorization logic in the security filter and if everything goes through, you can use this information to LOG that clientId and the request that the client made.
This way you can kill 2 birds with one stone : Implement a security layer & log the information about customers (what calls they are making, how many time etc. etc.). In case you don't want to implement security filter just yet (as you mentioned it might be in the future), for now, the clients can just pass on the "clientId" (base64encoded or not, upto you) as a part of "Authorization" header. If all the calls are from a "trusted" network, it should be ok, although not as secure. This way, when you ACTUALLY implement a JWT and Oauth based security layer, all you have to do is change your ContainerFilterRequest logic to parse out access_token instead of client id (as mentioned in step # 2).
I hope this helps ! For more information on security filters you can have a look at this answer: Basic Authentication of a resource in Dropwizard. It says dropwizard, but it mostly talks about JAX-RS.
To implement full AuthN/AuthZ layer for consumer tracking would be an overkill for now.
We thought to use either to Authorzation header to pass custom client_id token:
Authorization: Custom <Client_Id>
or to use some limited version of JWT (no signatures as there no intent to validate them)
as access token
Authorization: JWT <JWT>
Where JWT could be:
{"alg":"none","typ":"JWT"}
{
"iss":"Client_ID",
"aud": REST Service URI,
"iat":1328550785
}
I do not see description of access_token format in the specification https://datatracker.ietf.org/doc/html/rfc6749#section-1.4
Are there any contraints to use JWT as access token?

Protecting Image resources with OAuth2 Bearer Tokens

I've created a number of Web Services that produce/consume JSON data and I've protected them using OAuth2 and Bearer Tokens, which works fine.
Now however I need to build a similar Web Service that produces images rather than JSON (so JPEG/PNG data). For consistency I would also like to protect the service with OAuth2/Bearer Tokens, but doing so would make the service more challenging to consume in browser based applications that wish to display the image data using the <img> tag, because the <img> tag will not send the necessary Authorization: Bearer ...bearer-token... HTTP header.
I can see two ways round this:
Browser based clients of the Service would use XHR Level2 and the Blob and Blob URL schemes from HTML5 to retrieve the image data as a Blob, use the Blob URL scheme to generate a URL for the Blob and then dynamically create an img tag that refers to the Blob URl. A lot of work just to display an image!
Modify the OAuth2 infrastructure to generate a Http cookie in addition to the Bearer Token. Modify the service Authorirzation to accept EITHER the Authorization: Bearer ... OAuth2 header OR the cookie as proof of identity. Cookie to have same lifetime as bearer token, httpOnly etc. Browser based clients can just rely on browser cookie support to get access to service, can deference image data via <img> tag as normal. Easy to use for browser clients, but non-standard. Security risk profile seems the same for either bearer token or cookie.
Am I overlooking any security issues with the latter approach?
Are there any alternative approaches for protecting image/media resources with OAuth2?
I assume you are using the user-agent-based application profile in terms of getting a bearer token into the browser base app.
The OAuth Bearer Token spec supports sending the token as a query parameter ?access_token=mF_9.B5f-4.1JqM. The javascript in your browser could add the token as a query parameter to your img links.
This would be more standards based, but then you would have to worry about the access_token value leaking out in logs, etc. I think the security trade offs would really depend on the scope of those bearer tokens, and how important these images are to protect.
I think opening up your OAuth infrastructure to accept cookies could open you up to new attack vectors. RFC 6750 specifically calls out the risk of CSRF attacks
Implementations that do store bearer tokens in cookies MUST take precautions
against cross-site request forgery.