torii gets authorization code instead access token - ember.js

I have an ember app that connects with github, but the authentication flow returns the authorization code, not the access token, and I don't really know how to do the exchange...well, at least I didn't found any examples on the internet.
I'm kinda new to ember, this is what I got so far
authenticator/torii.js
import Ember from 'ember';
import ToriiAuthenticator from 'ember-simple-auth/authenticators/torii';
export default ToriiAuthenticator.extend({
torii: Ember.inject.service()
});
torii-providers/github.js
import GithubOauth2Provider from 'torii/providers/github-oauth2';
export default GithubOauth2Provider.extend({
fetch(data) {
return data;
}
});
I know I may have to change something in the provider, but I don't really know where to start

I've used Torii to do GitHub auth myself. Here's my advice:
Drop ember-simple-auth and just use Torii directly. Ironically, ember-simple-auth's Torii wrapper isn't "simple".
You should go over Torii's docs to familiarize yourself with the library.
In your config/environment.js, configure Torii. Example:
torii: {
sessionServiceName: 'session',
providers: {
'github-oauth2': {
// your api key goes here
apiKey: '',
// link to your app goes here
// in development mode, it should be http://localhost:4200
redirectUri: '',
// specify OAuth scope here
scope: ''
}
}
}
Create a file called torii-adapters/application.js. Here you will need to implement the three methods .open(), .fetch(), and .close(). Note that you will receive the authorizationCode as a parameter for .open(), which you should exchange (with your auth backend) for an access token.
Oh, and you'll need an OAuth backend that keeps your client secret private. You send the authorization code from your Ember app to your OAuth backend, and the OAuth backend responds with an access token.
If none of that made any sense to you, check out this blog post, which has a good summary of OAuth. You should understand the big picture so that filling in the details is easy. :)

Related

How to implement an Ember Simple Auth using an external redirect

Here's my workflow.
User presses a login button.
User is redirected to the API which redirects to a login page on a third party site (ADFS SAML).
User authenticates there, is returned to the API which decodes the response, creates a user and a JWT token (both stored in a datastore), and then redirects the user to Ember with a ?token= query parameter.
What I'd like to do is work this in to a custom ember-simple-auth authenticator (and authorizer?) in order to take advantage of the niceness of session and Authorization headers from there on.
Currently I've hacked an authenticator to do just the redirect to the identity provider. The rest of the API workflow is working. And I'm catching the token in a route on the way back and populating a User resource via a call to the database. But I feel that I'm heading down the wrong (and the long) path.
Any thoughts? Is this something that ember-simple-auth-token is designed for?
I solved this in last month. what i did was
click the login
redirect to the adfs
adfs login success-> redirect to my backend
backend generate a sso temp token with access token details which is
already there and only valid for 2 minutes.
backend redirect web with a GET with params of sso temp token
frontend take the params of sso temp token and make another post
ajax request to backend
Api will validate sso temp token and provide details ( access
token and refresh token ) to the user
read response data for the post request in 6 and update on ember
simple auth service using authenticate interface ( you can
customize this using custom authenticator )
here is the custom authenticator class
import Base from 'ember-simple-auth/authenticators/base';
import {isEmpty} from '#ember/utils';
export default Base.extend({
authenticate(data) {
return new Promise((resolve, reject) => {
if(data.access_token!=null){
resolve({
scope: data.scope,
access_token: data.access_token,
});
}else{
reject();
} })
},
restore(data) {
return new Promise((resolve, reject) => {
if (!isEmpty(data.access_token)) {
resolve(data);
} else {
reject();
}
});
},
});
i have created a route to handle in the frontend to get the token which is sent by backend. so the route takes sso token by a get param ( cause backend cannot do a post to emberapp) so when the route triggers i catch the param in route and do a post method again to validate the token.
we are using redis generated tokens. so since this question is asked about the emberjs i illustrated the answer to support you on frontend. i have illustrate the concept as well to show what you need to do. so its up to you to dig up and find more about it. like how to create temporary JWT token, how to validate it, how to redirect to you to your backend with claims from the adfs and etc. i think i provide answer to the initial question you asked which is
"How to implement an Ember Simple Auth using an external redirect"

How to persist current logged in user details across page reload in EmberJS?

I use ember-simple-auth to manage authentication in my ember app.
The addon provides a session library which apparently stores the response from API server when I login using token authentication. The response contains typical oAuth2 response like access token, refresh token, expiry time etc. The library provides a boolean variable which tells if the user is authenticated or not currently.
I use an instance initializer which uses this boolean variable to fetch and store current user details. The code looks like this:
// app/instance-initializers/current-user.js
import Session from "ember-simple-auth/services/session";
export default {
name: "current-user",
before: "ember-simple-auth",
initialize: function(container) {
Session.reopen({
setCurrentUser: function() {
if (this.get('isAuthenticated')) {
container.lookup("service:store").find('user', 'me').then((user) => {
this.set('currentUser', user);
});
}
}.observes('isAuthenticated')
});
}
};
This works fine when I login and navigate across different routes in the app. The problem comes when I reload some page. The current user details somehow get erased and this setCurrentUser is also called but it gets called after all the hooks in the current route are called. So in hooks like model, beforeModel, setupController etc. session.currentUser is not set and it is set only after all these hooks are called.
How to avoid this? How to make the current user details available in route hooks on page reload?
New Answer
Completely ignore the below answer for now. Try to change your initializer to only fire after ember-simple-auth, like below:
// app/instance-initializers/current-user.js
import Session from "ember-simple-auth/services/session";
export default {
name: "current-user",
after: "ember-simple-auth",
Have a look at this part of the docs, some more information there regarding the initializer, and the let me know if you are using the following route mixin:
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
Previous Answer
I recommend you read through the session stores in the readme and try switch between session stores temporarily to see if that fixes your problem. Otherwise implement your own custom session store with local storage to make sure the persist & restore hooks work like expected.
The object you'll extend in that case looks like this(copied from readme):
// app/session-stores/application.js
import Base from 'ember-simple-auth/session-stores/base';
export default Base.extend({
persist() {
…
},
restore() {
…
}
});

Ember Simple Auth Logout Action with Django Backend

I'm using ember simple-auth library with ember simple-auth-token.
However, every time I perform a logout action, django does not delete the token of the logged in user.
I should point out that the frontend works like a charm!
I am wondering if there should be a change in the frontend or in the backend code.
The invalidate() method should normally take care of the token refresh action, right?.
Here is my code, which is pretty much the same as the code presented in the README of ember simple auth.
controller/application.js
import Ember from 'ember';
export default Ember.Controller.extend({
session: Ember.inject.service('session'),
actions: {
invalidateSession() {
this.get('session').invalidate();
}
}
});
Thanks in advance!
ember-simple-auth-token's authenticators don't implement the invalidate method that called upon session invalidation and can be used to send a request to the backend to invalidate the token. Without that method being implemented Ember Simple Auth simply deletes the token on the client side.
You should be able to extend the ember-simple-auth-token authenticator you're using and implement the invalidate method so that it sends a token invalidation request to the backend. Be sure to return a promise though.

Extending/modifying ember-simple-auth to check for auth cookies

I need to modify adaptive.js in ember-simple-auth for my app.
Ultimately I want the restore method to look for two particular cookie security tokens that is shared across our platforms and construct the simple auth localstorage object based on these cookies as a last resort if localStorage authentication data does not already exist in order to determine if the user is already authenticated.
I realise you can create a custom authenticator however the problem with extending Base is that when restore is called on your custom authorizer ember-simple-auth has already looked up localstorage for your auth data. If this isn't available restore never gets called. For this reason I believe I need to extend or modify the simple auth node module to my requirements.
Below is my simple attempt at trying to modify adaptive.js in ember-simple-auth within my app however when restore gets called it's never through the below:
import AdaptiveStore from 'ember-simple-auth/session-stores/adaptive';
AdaptiveStore.reopenClass({
restore(){
alert('do custom stuff here');
}
});
Using reopen worked for me:
import AdaptiveStore from 'ember-simple-auth/session-stores/adaptive';
export default AdaptiveStore.reopen({
restore(){
alert('do custom stuff here');
}
});

Ember-simple-auth: How to add authorization header to browser-initiated requests

I'm using oAuth2.
The DataAdapterMixin automatically adds the Authorization header to all Ember Data requests. The session service authorize method can be used to add it to Ajax calls, but how can I ensure the header is added to GET requests made from the browser. I've tried creating a custom authorizer as explained in the docs, but the authorize method is not called.
The my application stores scans of invoices and statements (usually pdfs) which can only be seen by an authorized user. Based on the user's actions, I am changing the data attribute of an object tag.
This
<object data={{attachViewURL}} width="800px" height="1200px">
is rendered as something like this:
<object data="/scans/attachments/11" width="800px" height="1200px">
This works fine except the authorization.
Any advice would be most appreciated. I'm new to Ember, so if I am going about this the wrong way, please let me know.
In lieu of you answering my comment, i'm just going to put my solution here:
import Ember from 'ember';
import SimpleAuth from 'simple-auth/authorizers/base';
export default SimpleAuth.extend({
authorize: function(jqXHR) {
var token = this.get('session.secure.token');
if (this.get('session.isAuthenticated') && !Ember.isEmpty(token)) {
jqXHR.setRequestHeader('Authorization: ', 'Bearer ', token);
}
},
});
You'll likely want to do a bit more checking etc, but that's pretty much all you need to do to actually set the header; just overriding the authorize function that is built in to ember-simple-auth to set a header once the authorization has passed (As defined by both the session.isAuthenticated boolean and passed token
EDIT:
I forgot that you need to also define that you're using your local authorizer in your simple-auth config (that tripped me up for a while because I assumed that ember-simple-auth would use the overriden local authorizer by default):
ENV['simple-auth'] = {
authenticationRoute: 'login',
authorizer: 'authorizer:local',
session: 'session:user-session',
routeAfterAuthentication: 'dashboard'
}
I'll try and dig up where I got this from (because the ember-simple-auth docs aren't particularly good at describing self-rolled authorization mechanisms...)
EDIT 2:
As marcoow pointed out (and he should know, he wrote ember-simple-auth!), this is pre-1.0 behaviour. The authorizer is now part of the session service, which needs to be injected into the application. See ember-simple-labs pre-1.0 upgrade
The only approach I've managed to get working is to include the access token in the generated URL and then manually authenticate on the back end.
The URL ends up looking something like:
<object data="/scans/attachments/11?token=a0a59197-afab-438a-b6cf-11237e51a2d5" width="800px" height="1200px">
I'm not proud of this workaround. It's horrible programming, but it's the only thing I've gotten working so far.