I have an MVC site that uses authentication and authorization successfully. I am trying to query an api portion of the site using jquery and the load method. I have attempted to then use
User.Identity.GetUserId()
and this fails, as the request is not authenticated. The page with the ajax request is sucessfully logged in. Is it possible to access its authentication token and pass this with the load request, or do I need to generate a new token in javascript?
EDIT: After some more research, I have found that this line in the WebApiConfig file:
config.SuppressDefaultHostAuthentication();
Is what is disabling the cookie validation for ajax requests. It makes it so only the token method is evaluated. By default MVC uses cookies, and web api uses tokens. I was trying to utilise two different authentication schemes. As the cookie is sent automatically with the ajax requests, the User.Identity is then filled. This answers my original question.
However, this is considered insecure and allows for CRSF attacks. Therefore, token is desirable.
So, reworded, can you use an existing authentication cookie with the /token endpoint to generate an authentication token?
I think you can do the following steps to achieve your goal:
Read authentication cookie on the client using jquery cookies plugin or whatever.
Create an Web API endpoint to handle AJAX authentication which accepts cookie as a body parameter.
Parse authentication cookie, get user information from it and return a token.
Use generated token for subsequent reqeuests.
Ive found a workable solution with the minimum amount of effort.
The ApplicationOAuthProvider is the default provider. It provides an endpoint at /token that you can call with your username and password. In return it provides an authorization cookie, and more importantly a bearer token in the body of the response.
The login flow for the user is unchanged. They visit a log in form, and enter their credentials. This then calls the /token endpoint transparently, returning the response token and cookie. This token can then be saved using javascript to the local or session storage:
localStorage.setItem("token", "value");
This can then be retrieved for any pages loaded in the same browser session. You load this value and pass it in the headers of the ajax request, which then authenticates with the web api.
Use session storage if the user specifies they should not be remembered, otherwise local storage will mean the token is available more often. You do have to check both stores however, and there is a risk the token is invalid from expiration. If this occurs as signalled by an authorization error in the ajax request, you can easily display a message and redirect the user to the sign in page.
Related
It is my understanding that, as someone that has recently started using JSON web tokens that, once an access token expires, a new one may be generated using a refresh token.
I currently have some middleware on my server configured such that, if a JWT verification fails, it uses the refresh token to generate a new access token and then attempts the verification process again. If this succeeds, it sends a response with the new access token attached. If it fails, it sends a 401 error.
For this to work, however, the client must send both the access and refresh tokens. My fetch requests are currently configured such that they send the access token under the Authorization header as Bearer [token].
However, when reading the JWT docs, I have come across nothing that refers to the correct manner in which to send the refresh token. A brief search returned that it should be sent in the body of a POST request, however, given I am currently sending both tokens in all fetch requests I make, this would not work for GET requests.
Should I be sending both tokens in all requests? If so how should I send the refresh token in a GET request. Given it is stored in the client cookies, I have considered extracting it from there, though I'm curious if there is a better/more generally accepted method.
I'm exploring JWT and OAuth2 for a Javascript Single-Page-App which will make calls to a backend server-side API. I've come up with a security process that involves using two tokens and gives me the advantage of avoiding the need to have an additional server-side session storage:
The first time the client JS app is loaded up, user sends username/password over SSL to OAuth2 server. The server will set a cookie (normal cookie that is readable by client, without any HttpOnly flag set) that contains a JWT with an OAuth2 access token inside it's claims (along with some other non-confidential data in the JWT claims, ie. user's first/last name, country, role/permission). The server will also set a HttpOnly cookie that will contain the OAuth2 refresh token.
The cookies set by the server will be included on every request from the client automatically (always over SSL), so the server will receive the JWT (see step 3) and both confirm the signature and confirm the OAuth2 access token. The server will also confirm the refresh token. Since the server is checking the access token and refresh token against the OAuth2 database on each request, this gives us the ability to revoke access (which we would not be able to do with the JWT signature alone). We can do a "hard" revoke which revokes both access and refresh token. And we can do a "soft" revoke which just revokes the access token (for instances where perhaps some data that we keep in the JWT claim gets updated, ie. user changes their name or country or role). A soft revoke would be invisible to the client end user (it wouldn't disrupt their logged in status).
In step 2 above, the server will actually look for the JWT in a specific header set by the client (instead of the cookie set by the server). For example, the client JS app will read the JWT from the cookie and then set the JWT in another part of the header. By requring the client to explicitly set a header key/value containing the JWT shows that the client was able to read it's own cookie, thus preventing against XSRF (cross-site request forgery).
The HttpOnly cookie that contains the refresh token ensures we are protected against XSS (ie. some malicious javascript that sneaked its way onto our client). If our JWT was stolen, access still wouldn't be granted because the refresh token was not also seen or stolen by the JS.
With this approach we get all these benefits:
We don't need a server-side session storage. Since we are hitting an OAuth2 server then we can simply just include some extra data in the JWT that we return (non-confidential data). We wouldn't need to re-query/refresh the data in the JWT every time, but perhaps only when the OAuth token is revoked (ie. was revoked when some user data was changed that we include in the JWT's). No need to tackle the storage/scaling requirement that comes with using sessions. The client JS app can use this data like any other app would normally use sessions. For instance I can display a user's name on every "page" in the app. We could also just use websockets, but the JWT is a good backup place for adding some data if we need it.
We are protected against XSRF.
We are protected against XSS.
We can revoke access and also log users out (which is not easily possible with JWT alone).
SSL prevents man-in-the-middle attacks.
The JWT adds a little extra security hurdle for attackers to pass versus just a normal JSON object serialized in the cookie. The attacker would need to get the server-side key for signing JWT's (in addition to OAuth access). The JWT is also a standard, so easier for a trusted developer to work with.
The JWT can be easily passed down to other micro-services sitting behind the OAuth layer to use service-to-service. We can pass it around as "session like" data access to all the services on a request. If a service want's to change something in that data, then they can inform OAuth2 server and it will "soft" revoke the user's current JWT (not really much different from the process with a session storage) and provide a new one.
I haven't exactly seen anyone detail a security process like this yet. Many I see seem to only talk about using JWT with an OAuth2 access token inside and don't elaborate much more. So my question is, does this approach indeed provide the benefits I listed above? If not, what am I missing here and what security hole have I not covered for?
I'm working on a javascript application using a REST API.
Authentication is made with JWT tokens stored in cookies
Right now, this scenario is implemented:
user sign in with credentials. Client calls POST /token to authenticate
server responds with a HTTP-only cookie containing the token.
once authenticated, client makes another request to get all user data (GET /me)
I would like to make this process as fast as possible and reduce the number of server requests as much as possible. I thought about combining /token and /me calls and get token and user data in the same request.
That could be done in different ways :
in the claims of the token, but client won't be able to use it as it's in a HTTP-only cookie.
in another, non HTTP-only, cookie but that will be sent uselessly with every future request, so I don't like this solution
in the response body when server sends the cookie after authentication but I have the feeling that it goes against the REST principles as we send user data from an authentication endpoint.
Is there a way to make this process more simple while respecting standard processes and REST principles?
I personnally use Cookies as a storage, but not in HTTPonly mode. In this case, the simplest is to encode the information you need inside the token.
Are you forced to use HTTP-only cookies? Is it an option for you to change it (in fact, for that you must master the authorization server)?
Another thing : using GET to pass credentials isn't safe as you probably pass your credentials in the URL, which can be fetched from server logs. Prefer POST (and HTTPS of course).
Few pointers about JWT and their storage stategies:
Tokens vs Cookies
Where to store the tokens?
Threats of token theft
How to send the JWT to a client just after client has authenticated without using Cookies when an html document body is needed to be sent too?
There are docs, blog posts, and tutorials, explaining the cookie-less jwt authentication and leveraging the use of Web Storage API to save the jwt client side. But all of them are trivial examples without sending an html document in http response body upon an authentication which is necessary in some real world applications I can imagine. A cookie can be sent in cookie http response header alongside with an html document in same response's body, I could not still come across a post explaining to do this with a jwt in response instead of a cookie. As I know there is not an API to reach the response headers from javascript in browser if one want to send the jwt in response headers alongside html document in response body.
I have handled your scenario in my project and it can be done in two ways depending on your technology stack you are using and environment constraints, and using OAuth is not mandatory.
Method 1
Send the JWT embedded in the HTML page as a tag. It wont be rendered on the page but can be parsed by you. However, it will be visible in the source window of the browser but it doesnt matter as that would be a protected page and once the next page is rendered, it will not be available.
Method 2
You can send the JWT in a cookie for the first time with a http-only constraint. Handling it over https would bring in extra leverage. Also, like you mentioned, you can delete the cookie.
In case you are using AngularJS on your client side, you have the provision of securing cookies by restricting XHR from the same domain which would avoid the extra task of deleting the cookie.
In fact, #user981375 was mentioning about redirection which can be handled too by Method 1 above. In my case, server provided the redirection URL after successful login however, ajax wouldnt be able to see a 302 header instead would see a 200. So we intercepted that part on server and embedded the token into the 200 response page, i.e. redirected page which is parsed by the client.
I'm in the same boat, I could not figure out how to send JWT token to the client upon successful (or not) social login(s) where redirect was required. Things are simple when when you present user with a login/password and authenticate against your own server via AJAX, but no so simple when you 1) load your login page, 2) do a redirect to OAuth provider, 3) callback to your own server, 4) issue your own JWT token and ... then what?
There is a library out there that provides OAuth support from the client side. You authenticate against Facebook/Google (whatever) get their token back and then you make AJAX request to your own server for token validation. When token is validated by Facebook/Google (whatever) you can then issue your own JWT token with claims and send it as a response (AJAX) to your webpage.
Here is the library and nice article describing how to use it.
HTML documents are usually retrieved from a web application. Web applications are protected by a form of implicit authentication.
Web APIs are usually protected by explicit authentication and the JWT tokens are sent in an HTTP header (Authorization). This is not done automatically by the browser. You have to do this explicitly through JavaScript.
You could of course store the JWT token in a cookie and have it automatically sent to the server on each request.
See also my answer here.
I am trying to implement OAuth with my javascript client application.
I already have the server up and running.
My workflow is as following:
Open app
Check if token is present
Validate the token
If not present or not valid go to oauth server for the token
Get back to app and repeat 2 and 3
I everything is ok show my app
I am not sure how to implement point 2. I understand that I need to make another call to the server for this but where is the validation endpoint?
I only have /authorize, /user and /logout
Also how should the request be formed? Do I attach token as a GET parameter and thats all?
What if somebody intercepts valid the token?
Depends on your application, but since you have a javascript web application, that most probably can't keep it's credentials secret, you'll need to implement the Implicit Grant as stated in the OAuth 2.0 spec. If however your application CAN keep it's credentials secret, you should implement the Client Credentials Grant (server side application) because it's more secure.
I am not sure how to implement point 2
You should store your access token somewhere in your web application, for instance in localStorage.
The first time a user will access your web application, the user will have NO access token and NO session with your authorization server. Your web application could see if you have an access token by doing something like:
if (!localStorage.getItem('accessToken') {
window.location.replace('https://your-authorization-server/authorize?response_type=token&client_id=<CLIENT_ID>&redirect_uri=<CALLBACK_URL>&scope=<SCOPE>');
}
If there's no access token, you'll need to redirect to your authorization server so that the user can log in with the authorization server. After the user has logged in, the authorization server will redirect the user back to your web application (after the user has granted permission to whatever resource your web application likes to access on behalf of said user) with a valid access token. This access token must be exposed as a hash fragment named access_token, i.e:
https://web-app.com#access_token=123456789X
Now your web application can extract the access token and store it somewhere.
I understand that I need to make another call to the server for this
but where is the validation endpoint? I only have /authorize, /user
and /logout
Your authorization server requires a token validation endpoint. This endpoint will be used by your web application to validate said token (the one you stored somewhere, for instance localStorage). When this endpoint is called with an access token and it turns out the token is valid, the user can continue, otherwise the user will be redirected to the authorization server. If the user already has a session with the authorization server, the user will be redirected back immediately with a new access token, otherwise the user needs to authenticate (login) first.
Also how should the request be formed? Do I attach token as a GET
parameter and thats all?
Some send a GET request with the access token as a url query parameter, others send a POST request with the access token as the payload of the request body.
What if somebody intercepts the valid token?
Always use https and your access token should be valid for a limited amount of time.
Something to keep in mind is that because your application can't keep it's credentials secret, you need to Implement the Implicit Grant, this means you immediately receive the access token when the authorization server authorized the web application based on Client Id and domain. As opposed to Client Credentials Grant where you first receive an Authorization Code that needs to be exchanged for an access token. When using Implicit Grant you can NOT use Refresh Tokens. This means the user NEEDS to go through the entire flow with the authorization server to obtain a new access token. But this isn't really a big deal, because the user will already be logged in with the authorization server, resulting in an immediate redirect, so when implemented correctly in the web application, the user won't notice.
This is just covering it in broad strokes, it really helped me (and I advise you) to read the OAuth 2.0 spec. Hope this helps you out a bit, OAuth is a complex subject!