Ember Hub Me aims to quickly integrate with multiple identity providers using Auth0.
npm install --save-dev ember-hub-me
There are several configuration options.
- (REQUIRED) - clientID - Grab from your Auth0 Dashboard
- (REQUIRED) - domain - Grab from your Auth0 Dashboard
- (OPTIONAL) - rules - Array of rule objects. - {host:'http://localhost', authrorizer:’oauth’}
- (REQUIRED) - host - The hostname to pattern match against. Must defined protocol (http, https) and port(if different than 80).
- (OPTIONAL) - authorizer - Default is oauth. The name of the authorizer to run when any call is made with the corresponding hostname.
- (OPTIONAL) - prompt - Default is true. If the user is not authenticated for this profile, prompt them to sign in.
- (OPTIONAL) - routeAfterAuthentication - The route to transition to after authentications. Defaults to
index
- (OPTIONAL) - requestRefreshToken - Should we request a refresh token. If yes, this will keep the user logged in until they manually logout, or the token is revoked. Defaults to
false
//environment.js
ENV['hubme'] = {
clientID: "auth0_client_id",
domain: "auth0_domain",
routeAfterAuthentication: "dashboard",
requestRefreshToken: true,
rules:[
{host:'http://api.myapp.com'},
{host:'http://api.otherapp.com', authorizer:'my-custom-authorizer'}
]
}
To work properly, you must use the application_route_mixin
with your application route.
//app/routes/application.js
import ApplicationRouteMixin from 'ember-hub-me/mixins/application-route';
export default Ember.Route.extend(ApplicationRouteMixin, {
...
});
Ember Hub Me currently uses Auth0 Lock
in popup mode. For this reason there are no additional routes required for the login process.
Once the application_route_mixin
is added to your app route, you will be able to call the following actions:
<!-- app/templates/application.hbs -->
<a {{action 'login'}} href=''>Login</a>
<a {{action 'logout'}} href=''>Logout</a>
<a {{action 'register'}} href=''>Register</a>
login
and register
will both call the Auth0 Lock panel for standard user flow.
logout
will attempt to destroy the refresh_token if there is one, and then clear all session data. It will then hard reset the window.location to wipe all in memory data.
This is handled using a mixin as follows:
//app/routes/protected.js
import AuthenticatedRouteMixin from 'ember-hub-me/mixins/authenticated-route';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
...
});
This will force the user to login if not already authenticated. This will happen before the model
hook is invoked.
What about sending authorization info with requests? How do I add the right headers?
This is handled by using authorizers. Out of the box there is the OauthAuthorizer.
Hub Me works by pattern matching against all requests using jquery's Ember.$.ajaxPrefilter(...);
function. Rules can be defined at author time via the environment file, or at runtime via the hub.createAuthorizationRule(options)
function.
//environment.js
ENV['hubme'] = {
clientID: "auth0_client_id",
domain: "auth0_domain",
routeAfterAuthentication: "dashboard",
requestRefreshToken: true,
rules:[
{host:'http://api.myapp.com'},
{host:'http://api.otherapp.com', authorizer:'my-custom-authorizer'}
]
}
It is important to define the complete url, including the protocol
and port
if different than 80
hub
in injected on all routes, controllers, and adapters.
//controllers/index.js
init: function(){
this.get('hub').createAuthorizationRule({host:'http://localhost:4567', authorizer:'sinatra-auth'});
this.get('hub').createAuthorizationRule({host:'http://localhost:3000', authorizer:'express-auth'});
}
//authorizers/custom-auth.js
import Ember from 'ember';
export default Ember.Object.extend({
//Inject stuff
hub: Ember.inject.service('hub'),
//This function will get called when a match is found
ajaxPrefilter: function(options /* originalOptions, jqXHR */){
var token = "Bearer %@".fmt(this.get('hub.session.jwt'));
if(Ember.isBlank(options.headers)){
options.headers = {};
}
options.headers.Authorization = token;
}
});
//initializers/custom-auth.js
import CustomAuth from 'authorizers/custom-auth';
export function initialize(container, application) {
// Add the authorizer to the authorizer namespace
application.register('authorizer:custom-auth', CustomAuth);
}
export default {
name: 'custom-auth',
initialize: initialize
};
- Oauth authorizer - Once authenticated with Auth0, this authorizer will send the following header with all requests matching the hostname.
Authorization: "Bearer jwt"
If the user is not authenticated, no adjustment to a request will be made.
This is the flow of client/server authentication used by hubme.
- The user authenticates with Auth0.
- Auth0 returns a JWT signed by the client secret
- The client safely stores this jwt
- With each request to a remote server, we send the jwt along in the Authorization header
- The server validates the jwt using the client secret and expiration
- If all is well in the jwt world, it does all needed authorization logic and sends back the requested data or a 401 status
Remember, Auth0 base64 encodes the client secret. you will need to urlsafe base64 decode when validating the jwt on the server or in the client
The goal of this addon is to allow the client to simply setup rules, and have all the authentication and authorization for that host happen in the background. Auth0 streamlines the authentication part, so the task for Ember Hub Me will be to manage those profiles and plug in the user workflows.
- Complete test coverage
- Manage state across multiple windows and tabs
- Allow for linking of providers, fb, github, etc. into the main identity
- Allow for an adapter to trigger authentication if a 401 is returned on specific host
- Create authorizers for many identity providers
- Options to combine identities through Auth0