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.
Related
So I have a simple ESA setup with a custom authenticator/authorizer wrapping Basic HTTP Auth. The login route uses UnauthenticatedRouteMixin and the login controller is basically just authenticating against the custom authenticator, and afterwards fetches the user object from a REST service:
export default Ember.Controller.extend({
session: Ember.inject.service('session'),
actions: {
login() {
var self = this;
let { userName, password } = this.getProperties('userName', 'password');
this.get('session').authenticate('authenticator:basicauth', userName, password).then(function ()
{
self.store.queryRecord('user', { loginname : userName }).then( function (user) {
console.log(user.get('id'));
self.get('session').set('data.filterUserId', user.get('id'));
});
}).catch((reason) => {
this.set('errorMessage', reason.error || reason);
});
}
}
});
Now, in the first authenticated route (via AuthenticatedRouteMixin), for testing I also simply console.log the stored session property:
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
session: Ember.inject.service('session'),
model: function () {
console.log(this.get('session.data.filterUserId'));
},
});
In the console output, I observe that the model hook seems to be executed before the authenticator's promise is resolved, i.e. first I get "null", then the ID.
How can I make the AuthenticatedRoute wait for the actual login authentication to resolve?
Ember Simple Auth will transition to the routeAfterAuthentication as soon as authentication succeeds which is right when the promise returned by the session service's authenticate method resolves. You're only loading the user asynchronously after that though so that it is only loaded after the transition as been done already.
For an example of how to load data when the session becomes authenticated see the application route in the dummy app: https://github.com/simplabs/ember-simple-auth/blob/master/tests/dummy/app/routes/application.js
You must be aware that the session can become authenticated when the user logs in in the current tab/window but also when the user logs in in another tab or window (where the sessionAuthenticated event could basically be triggered at any time then) - that's why you need to load all data you need when the session is authenticated whenever the sessionAuthenticated method is called on the application route (of course you can handle the session service's authenticated event yourself instead of using the ApplicationRouteMixin) and not when the promise returned by the session service's authenticate method resolves.
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 :)
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);
});
});
}
My Ember app needs to authenticate users with Google OAuth 2. I want to be able to store the authentication tokens in a database, so I decided to put the authentication process on the server side, using Passport for Node.
When the authentication is over on the server, how do you make your Ember app aware of the Passport "session"?
Once authenticated thanks to the passport process, the client, in all its communications with the server, sends the user session along with its requests. If you want your Handlebars template to condition on the presence of a user, my approach was to set up the following request handler on the server:
app.get("/user", function (req,res) {
if (req.isAuthenticated()) {
res.json({
authenticated: true,
user: req.user
})
} else {
res.json({
authenticated: false,
user: null
})
}
})
And in my Ember route I do the following request:
App.ApplicationRoute = Ember.Route.extend({
model: function () {
return $.get("/user").then(function (response) {
return {user: response.user};
})
}
});
So that in my Handlebars template I can do the following:
{{#if user}}
<p>Hello, {{user.name}}</p>
{{else}}
<p>You must authenticate</p>
{{/if}}