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 :)
Related
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.
currently I'm changing my project from ember to ember-cli and run in a issue I can't get rid of. I am really not sure where the problem is, since I also updated ember and ember-data.
I get the Error:
Uncaught Error: Cannot re-register: `store:main`, as it has already been resolved.
I'm trying to load a user via the simple-auth Session.
import UserSession from '../session/user';
export default {
name: 'user-session',
before: 'simple-auth',
after: 'store',
initialize: function(container, application) {
container.register('session:user', UserSession);
}
};
and the session:
import Session from 'simple-auth/session';
export default Session.extend({
setup: function(authenticator, content, trigger) {
// Do not let setup trigger
this._super.call(this, authenticator, content, false);
// Lookup user and trigger events ourselves
var store = this.container.lookup('store:main');
console.log(store.find);
var self = this;
store.find('user', content.userId)
.then(function(user) {
self.set('user', user);
self.trigger('sessionAuthenticationSucceeded');
}, function() {
console.log('ERROR: Could not resolve user of session!');
});
}
});
the store.find is there but then the error breaks it.
I also tired to inject the store like this:
Ember-Simple-Auth currentUser example help required but had the same result.
Further I tried to make it via the instance-initalizer for ember-data beta.19.
I do stuff like this:
Session from '../session/user';
export default {
name: 'user-session1',
after: 'ember-data',
initialize: function(container, application) {
var store = container.lookup('store:main');
}
};
but this ends up in:
Uncaught TypeError: container.lookup is not a function
Using:
DEBUG: -------------------------------
ember.debug.js:4874DEBUG: Ember : 1.12.1
ember.debug.js:4874DEBUG: Ember Data : 1.0.0-beta.19.2
ember.debug.js:4874DEBUG: jQuery : 1.11.3
ember.debug.js:4874DEBUG: Ember Simple Auth : 0.8.0
ember.debug.js:4874DEBUG: -------------------------------
Thx for the help
------------------ EDIT --------------------------------------------
I updated my instance-initializers based on #Artych comment where I get the store.
I removed the custom session from simple-auth and tried it with reopening
ENV['simple-auth'] = {
//session: 'session:user', ...
My function:
initialize: function(application) {
var store = application.container.lookup('store:main');
Session.reopen({
setCurrentUser: function() {
console.log('never get here');
var accessToken = this.get('access_token');
var self = this;
if (!Ember.isEmpty(accessToken)) {
//never gets here, doesn't matter if I take other variables
}
}.observes('access_token', 'id', 'userId', 'user_id')
});
}
the problem now is that it never goes into "setCurrentUser". I still can logout and in. my autenticator:
authenticate: function(credentials) {
return new Ember.RSVP.Promise(function(resolve, reject) {
var ttl = 30*60*1000; // Request login for 30 minutes
var data = _.extend(credentials, {ttl: ttl});
Ember.$.ajax({
type: 'POST',
url: ENV.api + '/users/login',
data: data,
dataType: 'json'
})
.then(function(response) {
console.log(response);
Ember.run(null, resolve, response);
}, function(xhr, status, error) {
Ember.run(null, reject, error);
});
});
},
returns:
Object {id: "xI3sPSsgdOiHLd8DcFyuOE42KhbuO8gi8BjWBJRrgHgeCESWoma99C2RtvC6tnxG", ttl: 1800000, created: "2015-07-02T14:00:06.600Z", userId: 1}
As you can see, I added a bunch of observed variables: observes('access_token', 'id', 'userId', 'user_id') which I saw in different other questions but nothings helps.
Any idea on this?
Thx
I Solved it.
Simple don't use Ember Data 1.0.0-beta.19.2. I upgraded to 1.13.4 and I was able to get the store like before.
I'm having a lot of trouble getting ember simple auth with torii working at all at the moment using Ember CLI.
After creating a new Ember CLI app and installing torii, ember-cli-simple-auth and ember-cli-simple-auth-torii, I have a couple of buttons on my login page
Here is the contents of my routes/login.js:
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
googleLogin: function() {
this.get('session').authenticate('simple-auth-authenticator:torii', 'google-oauth2');
return;
},
facebookLogin: function() {
this.get('session').authenticate('simple-auth-authenticator:torii', 'facebook-oauth2');
return;
}
}
});
The relevant part of my environment.js file is:
var ENV = {
...
torii: {
providers: {
'google-oauth2': {
apiKey: 'api-key-here',
scope: 'profile',
redirectUri: 'http://localhost:4200'
},
'facebook-oauth2': {
apiKey: 'api-key-here',
redirectUri: 'http://localhost:4200'
}
}
},
...
};
When I hit the actions in my login.js, I get the following error:
Error: Expected configuration value providers.facebook-oauth2.apiKey to be defined!
or
Error: Expected configuration value providers.google-oauth2.apiKey to be defined!
Why is torii not picking up my environment.js configuration?
You need to create the app in facebook and google, get the api key and place it where it says:
apiKey: 'api-key-here'
in your environment.js
Turns out my problem was a simple one, the ember serve process needed to be restarted (Ctrl + c, and then re run ember serve).
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.
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);
});
});
}