0
votes

I am trying to set up an authenticator which would be valid for many providers, because in the backend I am using doorkeeper assertion method which handles the whole flow.

I have installed:

* "ember-cli-simple-auth": "0.8.0-beta.1"
* "ember-cli-simple-auth-oauth2": "^0.8.0-beta.2"
* "ember-cli-simple-auth-torii": "^0.8.0-beta.2"
* "torii": "^0.3.4"

I was looking at this issue Workflow for Ember-simple-auth, Torii and Facebook Oauth2 so I could write this:

# templates/login
<a {{action 'oauth2Authenticate' 'facebook-oauth2'}}>Login with facebook</a>
<a {{action 'oauth2Authenticate' 'google-oauth2'}}>Login with google</a>

# controllers/login
actions: {
  oauth2Authenticate: function(provider) {
    this.get('session').authenticate('authenticator:oauth2', { torii: this.get('torii'), provider: provider });
  }
}

# initializers/authentication
import Oauth2Authenticator from '../authenticators/oauth2';
export function initialize(container) {
  container.register('authenticator:oauth2', Oauth2Authenticator);
}
export default {
  name: 'authentication',
  initialize: initialize
};

# authenticators/oauth2
import Ember from 'ember';
import OAuth2 from 'simple-auth-oauth2/authenticators/oauth2';

export default OAuth2.extend({  
  authenticate: function(options) {
    var self = this;
    console.log(options.provider);
    return new Ember.RSVP.Promise(function(resolve, reject) {
      options.torii.open(options.provider).then(function(data) {
        var data = {
          grant_type: 'assertion',
          provider: options.provider,
          assertion: data.authorizationCode         
        };
        self.makeRequest(self.serverTokenEndpoint, data).then(function(response) {
          Ember.run(function() {
            var expiresAt = self.absolutizeExpirationTime(response.expires_in);
            self.scheduleAccessTokenRefresh(response.expires_in, expiresAt, response.refresh_token);
            resolve(Ember.$.extend(response, { expires_at: expiresAt }));
          });
        }, function(xhr, status, error) {
          Ember.run(function() {
            reject(xhr.responseJSON || xhr.responseText);
          });
        });
      }, reject);
    });
  }
});

# config/environment
ENV['simple-auth'] = {
  authorizer: 'simple-auth-authorizer:oauth2-bearer',
  crossOriginWhitelist: ['*']
};

ENV['simple-auth-oauth2'] = {
  serverTokenEndpoint: ENV.host + '/oauth/token',
  refreshAccessTokens: true
};

ENV['torii'] = {
  providers: {
    'facebook-oauth2': {
      apiKey:      '631252926924840',
      redirectUri: 'http://localhost:4200'
    }, 
    'google-oauth2': {
      apiKey:      '631252926924840',
      redirectUri: 'http://localhost:4200'
    }
  }
};
  • POST /oauth/token: I pass to server the following params: 1. grant_type="assertion" 2. provider 3. assertion="3dPartyToken"

I am not sure if it is the better way for my requirements, for now I am getting the problem that I cannot run open method of torii, anybody know what I am doing wrong? if you have a better solution to this issue would be very appreciated.

error: enter image description here

2
Do you want to exchange the third-party token with a token of your custom API?kunerd
@kunerd Totally, in the case of third party authentication /oauth/token must receive the next parameters (provider="facebook"|"google", grant_type="assertion", and assertion="3dPartyToken")Moh
In this case you should subclass the torii authenticator, override the authenticate method and when super resolves make the request to your server to exchange the token.marcoow
@marcoow do you mean such as I described in my question? I actually see it the same. It will be really nice if you could explain the flow by an example.Moh

2 Answers

1
votes

You shouldn't extend the OAuth 2.0 authenticator to authenticate with torii as OAuth 2.0 and torii are very different from an Ember Simple Auth point of view although most of the torii providers connect to OAuth 2.0 backends. Simply use the torii authenticator and pass the torii provider that you want to use as the 2nd argument to Session.authenticate. See this example to get an idea for how that works.

0
votes

Currently I'm using a similar approach as described in the question, but I inject torii into my authenticator via an initializer:

export default {
  name: 'custom-torii-oauth2-config',
  before: 'simple-auth',
  after: 'torii',

  initialize: function(container, application) {
    application.inject('authenticator:custom-torii-oauth2', 'torii', 'torii:main');
  }
};

After that it can be used within the authenticator like following:

this.torii.open(...)

I also thought about the solution marcoow mentioned in his comment, but for me it results in to much duplicate code with the oauth2-authenticator. Wouldn't an extension for the torii-authenticator be nice, which is handling exactly this flow?

Edit Important part of custom-torii-oauth2 authenticator.

  fetchOauthData: function(options) {
    var _this = this;
    return new Ember.RSVP.Promise(function(resolve, reject) {
      _this.torii.open(options.provider).then(function(oauthData) {
        Ember.run(function() {
          resolve({
            grant_type: 'authorization_code',
            provider: oauthData.provider,
            code: oauthData.authorizationCode,
          });
        });
      }, function(error) {
        Ember.run(function() {
          reject(error);
        });
      });
    });
  }