0

What is the right way to proceed the logout action of the User when using JWT, Rails API and a JS front-end framework, for example Ember JS ? What I'm actually doing is:

  • use Rails 5.2 as API
  • use Ember JS 3.3 as front-end
  • use Ember Simple Auth as OAuth add-on
  • example app, its master branch, works as needed
  • example app, its without login branch fails to logout the User
  • check the presence and pass in a token in every request between Rails API and Ember JS apps.

The questions I have are:

  • Should I keep a token value in the backend model (User, for example) ? I need it to make another request in the background on the backend side.

  • Should I set the token value to nil when the User logs out in the backend ?

  • What am I doing wrong with ESA as for logout action ?

  • Actually the token value is kept in a cookie on the client side (see https://github.com/simplabs/ember-simple-auth for more details). I followed their guides and the dummy app they provide.

  • I also had a discussion on Ember JS Forum and tried to follow some tips and advises, still no success.

Thank you.

belgoros
  • 3,590
  • 7
  • 38
  • 76
  • Did you figure this out? I know we were chatting on discord about this – NullVoxPopuli Sep 11 '18 at 09:20
  • @NullVoxPopuli, exactly :). Nope, unfortunately I still have no clues. – belgoros Sep 11 '18 at 13:04
  • @NullVoxPopuli will you see if you have anything to add/edit for my answer below? – handlebears Sep 11 '18 at 16:41
  • looks good to me :+1: @handlebears – NullVoxPopuli Sep 12 '18 at 01:33
  • @handlebears Thank you very much for taking time to write such a detailed explanation. Unfortunately, it does not provide much help without answering the questions I asked and still follows almost the same abstract and vast docs of most Ember Auth add-ons and plugins. I'm using ESA (ember-simple-auth). [Example app](https://github.com/belgoros/decastore-front), master branch, works as needed (login/logout). – belgoros Sep 12 '18 at 07:26
  • @handlebears But, having the main goal to remove login page, redirect to immediately to a corporate login gateway, the branch [redirect_to_login_gateway](https://github.com/belgoros/decastore-front/tree/redirect_to_login_gateway) does not log out the user. That's why after following the [discussion](https://discuss.emberjs.com/t/esa-how-to-redirect-to-corporate-login-page/15259), I still have no clues how to do that. Thank you. – belgoros Sep 12 '18 at 07:26
  • @belgoros are you really just looking for an example of how to write a custom Authenticator using JWT/cookies? – handlebears Sep 13 '18 at 11:16
  • I can post that if it’s helpful. Ultimately you have to make some implementation choices, which o tried to outline below. Let me know what seems to you to be the best fit. – handlebears Sep 13 '18 at 11:19
  • @handlebears Thank you for the response. I believe (if I'm not wrong) that ESA [OAuth2ImplicitGrantAuthenticator](http://ember-simple-auth.com/api/classes/OAuth2ImplicitGrantAuthenticator.html) already has all the stuff in place. I started to override its [invalidate](https://github.com/belgoros/decastore-front/blob/redirect_to_login_gateway/app/authenticators/oauth2-implicit-grant.js) method but still no success. I have impression that when calling `window.location.replace` in my index.js `beforeModel` hook, I still have the same cookies auth values, that's why I'm re-logged in immediately... – belgoros Sep 13 '18 at 19:04
  • Why/where are you using window.location.replace? That might be the issue. ESA uses a lot of route hooks and mixing, and maybe you are skipping something important by not using routing methods. If you are using Ember 2.16 or later, you can inject the router service and do transitionTo from services and components. I added an example invalidate hook with cookies to my answer below. – handlebears Sep 15 '18 at 06:59

1 Answers1

0

This answer applies to Ember 1.13 through at least 3.x.

Authentication comes in so many flavors that I think the right way to do it is whatever is an easy-to-understand fit with the back end.

Since your JWT is in a cookie, let's think of that cookie as the source of truth. Rather than doing something complicated to parse the cookie in a model hook, you could define a Service that has functions to grab the cookie, parse it, and either save the results to values on the service or return the values you need.

This gets you a few benefits. You can get the values from anywhere in your app, including adapters, and all the logic for auth lives in once place. On the other hand, you would have to handle async behavior yourself (i.e. if a route depends on having login info, you will have to manage the order of operations between authentication and route transitions).

Ember Simple Auth is quite popular because of this issue. Although there aren't out of the box features for JWTs in cookies, if you have an app with different states based on logged-in behavior, it might be a good investment to learn it.

The user model is kind of a middle ground between a hand-rolled service and Ember Simple Auth, since you can get the user model and rely on it throughout your app, plus get a little help with async. Just be careful not to scatter your auth code across your whole app.

Lastly, to trigger logout, I would create a function that destroys the cookie by setting the max age/expiration like this. If you are handling auth on a service, this means you could use Router Service and then transitionTo a login page. If you are using Ember Simple Auth, that functionality can go in the invalidate hook of your custom authenticator. Example:

invalidate() { this._super() document.cookie = "some_token_name=; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/" return Promise.resolve(); }

Lastly, for passing the token to authenticate requests, if you are using Ember Data, this can be done easily in the adapter's headers method.

handlebears
  • 2,168
  • 8
  • 18