Ember Auth Custom Authenticator - ember.js

When writing a custom authenticator using Ember.SimpleAuth with Ember-CLI, what exactly does the authenticate method of the custom authenticator need to return in order to establish a user as logged in? Below is the authenticator as it currently exists. We are using a phalcon rest api for the back end, so ultimately it seems that this method will need to hit that URL and authenticate the user on the server side, but what should the server return in order for ember.simpleauth to do what it needs to do?
import Ember from "ember";
import App from '../app';
import Base from "simple-auth/authenticators/base";
export default Base.extend({
tokenEndpoint: 'login',
restore: function(data) {
console.log('ran resotre');
},
authenticate: function(credentials) {
alert(credentials.identification);
alert(credentials.password);
},
invalidate: function() {
console.log('ran invalidate');
}
});

I would read Ember Simple Auth - API
authenticate needs to return a promise. Within the method, that promise needs to be resolved or rejected. A resolved promise would signal a successful authentication, while a rejected promise a failure in authentication. Here is how I structured a quick authenticate function.
authenticate: function (credentials, options) {
return new Ember.RSVP.Promise(function (resolve, reject) {
var loginPromise = Ember.$.post(<token url goes here>, {
username: credentials.identification,
password: credentials.password
});
loginPromise.then(function (data) {
resolve({
token: data.token,
userData: data.user
});
}, function (error) {
reject(error);
});
});
}

Related

Ember simple auth how to update when authenticate data is avaiable

Ember app is using adfs login.
when a successful login adfs will redirect to ember web app with a route and query parameters. those query parameters contain
access_token
refresh_token
user_id
scope
i need to update session of the ember auth with those credential data. how can i achieve this ?
You will need to authenticate a session with you params.
In order to being able to authenticate your session you will need to create an authenticator. Basically, this will provide you some method to being able to handle your session (invalidateSession, authenticate, restoreSession etc..).
For the authenticator creation check out http://ember-simple-auth.com/api/classes/BaseAuthenticator.html
It will look like something like so https://jsfiddle.net/e7nzoa6y/ but that's not exclusive you will have to custom it with you endpoint and stuff
Then once you have your authenticator, check out the doc at
http://ember-simple-auth.com/api/classes/BaseAuthenticator.html
In your controller, after injecting the session service,
you will be able to call the function authenticate with something looking like
this.session.authenticate(
'authenticator:YOUR_AUTHENTICATOR', queryParams
);
djamel your answer works for me and i have modified the code using your example as below
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({
access_token: data.access_token,
id: data.id,
agreement:data.agreement
});
}else{
reject();
} })
},
restore(data) {
console.log(data)
return new Promise((resolve, reject) => {
if (!isEmpty(data.access_token)) {
resolve(data);
} else {
reject();
} });
}
});
other than that i had to add
ENV['ember-simple-auth'] = {
routeAfterAuthentication: 'authenticated.index'
},
in config environment as well.

Issue with persisting session attributes after Torii authentication with ember-simple-auth

I'm following ember-simple-auth dummy app to implement authentication with torii. Everything works, and the app authenticates, but it fails to persist additional attributes returned from the server into data.authenticated. Just as the authentication method expects, I return a promise from the authenticator method with additional attributes token and email to be persisted into the session's data.authenticated:
// ~/frontend/app/authenticators/torii.js
import Ember from 'ember';
import ToriiAuthenticator from 'ember-simple-auth/authenticators/torii';
export default ToriiAuthenticator.extend({
torii: Ember.inject.service(),
authenticate() {
return this._super(...arguments).then((data) => {
return new Ember.RSVP.Promise((resolve, reject) => {
return Ember.$.ajax({
url: '/token',
type: 'POST',
dataType: 'json',
data: { 'grant_type': 'facebook_auth_code', 'auth_code': data.authorizationCode, redirect_uri: data.redirectUri }
}).then(response => {
Ember.run(() => {
Ember.Logger.log('response', response); // => {access_token: ".....", provider: "facebook-oauth2", token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkI…WxsfQ.xx6fBkwqwm7HeoOpnRWRVCKF71DdIhxyQggcfZ6325s", email: "..#....com"}
resolve(response);
});
}, xhr => {
Ember.run(() => { reject(xhr.responseJSON || xhr.responseText); });
});
});
});
}
});
Performing the authentication: this.get('session').authenticate('authenticator:torii', 'facebook-oauth2'); successfully authenticates, but the contents of data.authenticated are only {authenticator: "authenticator:torii", provider: "facebook-oauth2"} while I would expect it to persist token and email as well.
In addition to torii I also have a devise authenticator and it successfully persists additional attributes by default.
I'm using "ember-simple-auth": "1.1.0", ember-data 2.7.0 and ember 2.7.2 all via ember-cli-rails.
UPDATE 1: Weirdly, if I include authenticator: 'authenticator:devise' in my '/token' ajax response from the backend, the torii authenticator persists all attributes.

Ember simple auth Session not getting authenticated after calling resolve in custom authenticator

My authenticators/custom.js:
import Ember from 'ember';
import Base from 'simple-auth/authenticators/base';
export default Base.extend({
restore: function(data) {
},
authenticate: function(email, password, authenticateCallback) {
return new Ember.RSVP.Promise((resolve, reject) => {
Ember.$.ajax({
type: 'POST',
url: apiOrigin + '/api/v1/login',
data: {
email: email,
password: password
},
dataType: 'json'
}).then(function(userData){
console.log('login post success', userData)
authenticateCallback(userData)
Ember.run(function() {
resolve(userData.uuid)
})
})['catch'](function(main){
alert('login error ' + JSON.stringify(main))
console.error('\'caught\' error from login post request', arguments);
})
})
},
invalidate: function(data) {
}
});
And login/controller.js:
import Ember from 'ember';
export default Ember.Controller.extend({
session: Ember.inject.service('session'),
application: Ember.inject.controller(),
actions: {
authenticate() {
let { identification, password } = this.getProperties('identification', 'password');
this.get('session').authenticate('authenticator:custom', identification, password, (userData) => {
//TODO set these properties on ember-simple-auth's session object instead of application controller
this.get('application').setProperties(userData)
this.transitionToRoute('associate-device')
}).catch((reason) => {
this.set('errorMessage', reason.error);
})
}
}
});
My associate-device route is an AuthenticatedRoute.. I don't get an error, but instead, the last thing printed to the console is "Preparing to transition from 'login' to 'associate-device'"
Basically, ember simple auth documents here http://ember-simple-auth.com/api/classes/BaseAuthenticator.html#method_authenticate that "A resolving promise will result in the session becoming authenticated. Any data the promise resolves with will be saved in and accessible via the session service's data.authenticated property (see data). A rejecting promise indicates that authentication failed and will result in the session remaining unauthenticated."
However, my session does not seem to be authenticated after I successfully resolve my promise.
$.ajax has no catch method. This exception was hidden because I was copy-pasting away from the documentation for writing custom authenticators. To expose any exceptions occurring in your custom authenticators authenticate method, you should probably console.log them like so:
// app/controllers/login.js
import Ember from 'ember';
export default Ember.Controller.extend({
session: Ember.inject.service('session'),
actions: {
authenticate() {
let { identification, password } = this.getProperties('identification', 'password');
this.get('session').authenticate('authenticator:oauth2', identification, password).catch((reason) => {
// **CHANGE THE BELOW LINE**
console.error('exception in your authenticators authenticate method', reason)
});
}
}
});

ember-simple-auth: Persisting session in localstorage using custom authenticator

Setup:
Ember : 2.0.2
Ember Data : 2.0.1
jQuery : 1.11.3
Ember Simple Auth : 1.0.0 (jjAbrams Branch)
Ember CLI : 1.13.8
I'm using pretender to mock a server.
Usecase:
Using a custom authenticator to interface with the server.
Have 2 routes: login, protected (and by default index,application)
When I login with the right credentials, the authenticate method of the authenticator gets called and successfully logs the response object which is passed to resolve().
Observations:
After logging in and being directed to the protected page, Refreshing the protected route (Which has AuthenticatedRouteMixin) leads back to login page.
Localstorage has no values bound to it even after successful login.
Before login: ember_simple_auth:session -> {"authenticated":{}}
restore() method of authenticator never called.
Going to another route from the protected route after auth and coming back goest to login page again.
//authenticators/custom.js
import Ember from 'ember';
import Base from 'ember-simple-auth/authenticators/base';
export default Base.extend({
restore: function (data) {
return new Ember.RSVP.Promise(function (resolve, reject) {
console.log("RESOLVE",data);
if (!Ember.isEmpty(data.token)) {
//TODO Remove log
resolve(data);
} else {
console.log("REJECTING",data);
reject();
}
});
},
authenticate(credentials) {
return new Ember.RSVP.Promise((resolve, reject) =>
Ember.$.ajax({
url: '/token',
type: 'POST',
data: JSON.stringify({
email: credentials.identification,
password: credentials.password
}),
contentType: 'application/json;charset=utf-8',
dataType: 'json'
}).then(function (response) {
Ember.run(function () {
//This logs the expected information
console.log("Response", response, response.token, response.user);
resolve(response);
});
}, function (xhr, status, error) {
console.log("error", error, xhr.responseText);
var response = xhr.responseText;
Ember.run(function () {
reject(response);
});
}));
},
invalidate(token) {
return API.logout(token);
}
});
//environment.js
ENV['ember-simple-auth'] = {
store: 'session-store:local-storage',
routeAfterAuthentication: '/protected'
};
TLDR;
How do I make the session persist?
I got it all working together finally. Ember 2.0 and ESA 1.0
Here are the steps I took:
Create a new ember cli project
Update Ember and ember data values to ^2.0.0 in bower.json Source
Add ESA jjAbrams dep to package.json Source
run npm install && bower install
Gotchas: (This was the original problem which caused the problems described in the question)
If you're upgrading from older versions of ESA, all references to 'simple-auth/..' should be updated to refer 'ember-simple-auth/..' instead..
.. This include imports for authenticators, authorizers, stores, mixins and the Config key in the config/environment.js file.
All this shouldn't be an issue once ESA 1.0 and Ember Cli for Ember 2.0 comes out :)

ember-simple-auth custom authenticator using ember-data

I'm creating a frontend for a C program with an embedded web interface that has a simple REST api. I'd like to use ember-simple-auth with a customer authenticator and authorizer that talks to that api endpoint.
var Authenticator = AuthenticatorBase.extend({
restore: function(data) {
...
},
authenticate: function(credentials) {
var _this = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
... ??? ...
});
},
invalidate: function() {
var _this = this;
return new Ember.RSVP.Promise(function(resolve) {
... ??? ...
});
},
});
In the ember-simple-auth examples, I see the custom authenticator implementation that uses Ember.$.ajax to post to server like this:
authenticate: function(credentials) {
var _this = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
Ember.$.ajax({
url: _this.tokenEndpoint,
type: 'POST',
data: { username: credentials.identification,
password: credentials.password },
}).then(function(response) {
Ember.run(function() {
resolve({ token: response.session.token });
});
}, function(xhr, status, error) {
var response = JSON.parse(xhr.responseText);
Ember.run(function() {
reject(response.error);
});
});
});
},
But I'd rather use ember-data for this (I think) -- new to ember and ember-data, so it's not clear. Assuming my API endpoint is /session, what would my authenticate method look like with ember-data?
On a related note: I'm using ember-cli and running ember server for development. How do I tell ember-data to point to my C-based server for the REST calls? I'm trying this, but doesn't seem to be affecting the ember-data calls - they just go to the ember server:
// app/adapters/application.js
import DS from "ember-data";
export default DS.RESTAdapter.extend({
host: 'localhost:48880',
namespace: '/'
});
When you want to use Ember Data you'd need to have a Session model or so so that when you create an instance of that a POST to /sessions would be triggered. I don't actually think that makes sense though and you don't really get any benefits from using Ember Data in that case - I'd recommend to simply go with plain Ember.$.ajax and use Ember Data for your actual model data.