Sending JWT alongside html document in http response - javascript

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.

Related

REST API and JWT authentication : send data along token?

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

OAuth2 Implicit Grant with Ajax

I'm implementing OAuth's implicit grant type in a Javascript application using Angular. I would like to request a token using an AJAX request. When I make the request to my OAuth server, it responds with a 302 and a location header. As per the spec, the location is my configured redirect URL with a hash fragment containing the access token.
My problem is I have no way to read the hash fragments if it is an ajax request, since XmlHttpRequest automatically follows the location header. I can't seem to get any information about the initial response (the one whose status is 302, and has the location header.) If there were some way to intercept that response and read out the location header, I would be set.
I would like requesting a token to happen behind the scenes, without the user knowing it is even happening. (That is, without the browser's URL jumping all around.) I should also mention that I am working within an environment where SSO is available, and the user will most likely have already authenticated via SSO. As long as my OAuth server detects an SSO cookie, it will know the user has been previously authenticated and to just issue a token for this application, without needing to redirect to a login page.
Is there any way to read either the location header of the first response, or to read the URL that is redirected to? It seems that xhr itself goes to great lengths to prevent this, so I'm also wondering what is the reason for that?
oauth Implicit Grant usually opens the service login window so the user can accept the service integrator then provide their login credentials. Using JavaScript you can read the hash by implementing code similar to:
var browserRef = window.open(add your URL here, '_blank','location=yes,clearsessioncache=yes,clearcache=yes');
browserRef.addEventListener ('loadstart', function(event) { add code to read the hash)}

Passing credentials with Ajax load to Web API

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.

Authenticate client-side app to REST API using CORS with local strategy

The Problem:
Serving a secure API to a client side app using only a local authentication strategy. The red arrows are part of the knowledge gap.
Context:
That is --- client.example.com is making a POST to api.example.com/login where on success client.example.com can gain access to a GET service like api.example.com/secret.
An idea!
Implimentation of OAuth 2.0 with hybrid grant type sitting in front of API.
Why hybrid?
It wouldn't be an Implicit Grant Flow aka Client-Side Web Applications Flow because there is no redirection to API server too grant access token. (i.e.) "Is it ok for so-and-so to access your data?"
It wouldn't be a Resource Owner Password Flow because a Client ID and Client Secret are passed along with the request so it's assumed the client app is server-side.
OK... so what about a little bit of both?
What if we used a CRSF token on page load of client-side app, and POST it with user credentials too OAuth 2.0 authentication endpoint to exchange for access token? You would authenticate each subsequent request with the access token and CRSF token after a successful login.
A good Node.js OAuth 2.0 library I found:
https://github.com/ammmir/node-oauth2-provider
Help Me!
I can not find a working example of an authentication measure that solves this problem! Point me in the right direction?
Ultimately, the goal here is too authenticate a client side app to a REST api using CORS with a local strategy --- i.e. username & password --- even if the convention above isn't possible.
To Accommodate Bounty:
This is a client side app, so let's stay trendy.
I'm looking for a working example using the Node.js OAuth 2.0 seed above for the API/Auth server and a front end framework like Angular.js or Backbone.js to make requests.
The example should match the context described above.
I'm working on an app with a pretty similar architecture though the services are .NET Web API rather than Node and we're using DotNetOpenAuth for the OAuth provider. Rather than the hybrid approach you're suggesting we're doing the following:
x.com serves up a login page
login page POSTs back credentials to x.com
server side logic at x.com combines client_id and client_secret with the credentials to submit a token request (resource owner password credentials grant that you've
mentioned above) receiving back both a temporary access token and a
refresh token
the refresh token is encrypted into a cookie issued by x.com
both the cookie (with encrypted refresh token) and the temporary access token are then sent to the browser
the client app (angular in my case) can now use the access token to hit api.x.com for services (It appears you're well aware of the limitations of CORS... we hacked a version of angular's $resource to facilitate this but it wasn't pretty since we wanted to use all HTTP verbs and support IE9)
when the access token expires, the client side app can request a new access token from x.com
server-side, x.com decrypts the cookie to get at the refresh token and issues another oauth call for a new access token
This is fairly high-level but hopefully gives you a sense for how to tackle your situation. In my case, and it appears in yours, we didn't want to use session state or a database to store the refresh token but obviously exposing that to the browser introduces security concerns so the encryption of the refresh token is important (among other security considerations) and the use of the cookie eliminates the need for session state or other persistent storage on x.com.
Not an answer running for the prize. Just my 2 cents :)
On my web server,
I do my authentication through a rest call with login/password with basic authentication over https. This call delivers a key to the client (a one page web app).
Then every subsequent REST call is signed with the key. The server checks that the signature is correct and everything still happen in https.
This mechanism is quite used I believe.
I don't see the issue with cross domain. I have a single source anf if I need something from another source, I'd use JSONP.
I use nginx as an https->http forwarder.
Not sure how it competes with an OAuth2 solution.
I've built this example using Node and PassportJS to show how to authenticate the users with Facebook or Local Strategy. Both sides are on different domains as you described and it requires CORS enabled.
GitHub: https://github.com/pablodenadai/Corsnection
Live demo: http://corsnection-client.herokuapp.com/
I can't promise that I have time to write working example but I can show you 2 paths :)
The biggest deal is CORS. After you solve that problem it is easy to use $http service. So, first and probably easiest may be to configure reverse proxy in x.com webserver which points to api.x.com. I wrote article here
Second approach is better, and created for exactly this purpose, to authorise specific domain to use your resource. It involves a bit of coding in api.x.com so you don't have to change anything in new web applications served in other domains. You simply need to authorise CORS requests in api.x.com service.
Create table in database where you can manage list of authorised domains
Add in that table record "x.com"
in api.x.com add request filter/interceptor what ever tech term you use for method which should be invoked after request is handled and add in response Access-Control-Allow-Origin: x.com if request comes from x.com (in other words check in request header refer value match to any value in table above and put that value in Access-Control-Allow-Origin response header).
That is all :) After this if you know how to use $http or jQuey.ajax you will be able to POST/PUT/DELETE/... any request to api.x.com from any authorised domain in just few minutes.
I very similar idea using vinilla js web app and cross domain authentication to GAE backend or OpenID connect.
The web app is run on CDN. When click login link, it goes to respective login server and redirect back to the web app (with XSRF security token and HTTPS only cookie). Login server accept cross domain request with credentials. XSRF token has to be set (in header) with every request. cookie is set by the browser. Since it is HTTP only cookie, JS cannot read it. The technique is very secure.
Once login, you can get secure assess from login server.
For detail description, you can find here and open source repo here.

Youtube API: Is there a way to refresh an access_token in the client side v3 api?

https://developers.google.com/youtube/v3/guides/authentication
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
client_id=21302922996.apps.googleusercontent.com&
client_secret=XTHhXh1SlUNgvyWGwDk1EjXB&
refresh_token=1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ&
grant_type=refresh_token
The developer documentation lists a way to refresh an access_token on the back end. Is there a way to do this with the front end javascript calls?
If you're using the client-side web applications flow, which is appropriate if you're writing code in JavaScript that runs in the browser, then there's no way to get back a refresh token and periodically refresh it to get an access token. The accounts.google.com server doesn't support CORS, for one thing, so it's not possible to send the HTTP POST refresh request from your JavaScript.
What you can take advantage of is the approval_prompt=auto parameter behavior, which means that if a user has previously authorized access to your OAuth 2 client id for the same scopes, requesting a new access token can be done without any user intervention. So you can effectively get new access tokens indefinitely.
I'd highly recommend letting the Google APIs JavaScript client library handle this for you. In addition to the samples in the docs, you can take a look at this simple example which shows how you can handle the OAuth 2 flow in a way that only requires initial authorization.

Categories

Resources