The final cross-cutting service layer we are going to talk about is the authentication layer. The authentication layer is responsible for ensuring that the people interacting with our application are the people they say they are. There are several ways that someone can authenticate himself or herself with our application. They can use a basic username and password, they could use a certificate, or they can use an external authentication server that supports protocols such as OAuth and OpenID or they can use a two-factor authentication service such as Single Sign-On.
We are going to look at a service that frontends both a basic authentication service and OAuth 2.0 using the Google+ API. Since we haven't covered data services yet, the basic authentication part of the service will always return success with dummy data. We will complete this service in Chapter 5, Data Management.
The following authenticate
service acts as a frontend for the various authentication schemes our application will provide. It leverages the messaging service to receive the requests to use the various authentication services and then sends messages to invoke the login methods of the requested support services.
angular.module('brew-everywhere').factory('authenticate', function (messaging, events) { var currentUser = {}; var loginWithGooglePlus = function(){ messaging.publish(events.message._SERVER_REQUEST_STARTED_); messaging.publish(events.message._GPLUS_AUTHENTICATE_); }; messaging.subscribe(events.message._AUTHENTICATE_USER_GPLUS_, loginWithGooglePlus); var googlePlusAuthenticatedHandler = function(user) { currentUser = user; messaging.publish( events.message._AUTHENTICATE_USER_COMPLETE_, [currentUser]); messaging.publish(events.message._SERVER_REQUEST_ENDED_); }; messaging.subscribe(events.message._GPLUS_AUTHENTICATED_, googlePlusAuthenticatedHandler); var authenticationFailureHandler = function() { messaging. publish(events.message._AUTHENTICATE_USER_FAILED_); messaging.publish(events.message._SERVER_REQUEST_ENDED_); messaging.publish(events.message._ADD_ERROR_MESSAGE_, ['Log In Failed.', 'alert-warning']); }; messaging.subscribe(events.message._GPLUS_FAILED_, authenticationFailureHandler); var login = function(username, password){ currentUser = {name: {givenName: "Test", surname: "User"}}; messaging.publish( events.message._AUTHENTICATE_USER_COMPLETE_, [currentUser]); }; messaging.subscribe(events.message._AUTHENTICATE_USER_, login); var init = function(){ currentUser = {}; }; var authenticate = { init: init }; return authenticate; }) .run(function(authenticate){ authenticate.init(); });
The service responds to two messages _AUTHENTICATE_USER_GPLUS_
and _AUTHENTICATE_USER_
.
The _AUTHENTICATE_USER_
message invokes a stubbed-out method, which ignores the passed-in data and creates a user object with some dummy data in it and then responds with the _AUTHENTICATE_USER_COMPLETE_
message indicating the user has been authenticated.
The _AUTHENTICATE_USER_GPLUS_
message invokes the googlePlusAuthentication
service, which wraps the Google+ Sign-On API library that handles redirecting the user to Google+, allowing them to give the application permissions to access the user's Google+ account information as a means of authenticated identity.
The googlePlusAuthentication
service handles the _GPLUS_AUTHENTICATE_
message, which kicks the Google+ authentication process off with a call to the gapi.auth.authorize
method passing in the client ID of your Google+ application. Once the library returns, the callback handler parses the response and then proceeds to request the user's Google+ profile, which is returned in the _GPLUS_AUTHENTICATED_
message.
If the user fails to authenticate with Google+ or decides not to give permissions to our application, then the gapi.auth.authorize
method returns a failure response that causes the service to publish the _GPLUS_FAILED_
message. The source code for the googlePlusAuthentication
service is rather long so only a few of the methods are given in the following code:
var login = function () { var parameters = { client_id: defaults.clientId, immediate: false, response_type: defaults.responseType, scope: defaults.scope }; gapi.auth.authorize(parameters, handleResponse); }; var handleResponse = function (oauthToken) { parseToken(oauthToken); if (accessResults.access_token) { requestUserInfo(); } else { userProfileErrorHandler(); } }; var userProfileSuccessHandler = function (response) { if (response && response.data) { userInfo = response.data; messaging.publish(events.message._GPLUS_AUTHENTICATED_, [userInfo]); } }; var userProfileErrorHandler = function () { messaging.publish(events.message._GPLUS_FAILED_); }; var requestUserInfo = function () { var url = buildUserProfileUrl(); $http.get(url).then(userProfileSuccessHandler, userProfileErrorHandler); }; var onAuthenticateHandler = function() { login(); }; messaging.subscribe(events.message._GPLUS_AUTHENTICATE_, onAuthenticateHandler);
To learn more about using the Google+ API and how to set up a Google+ application that can be used with the Google+ API, check out the Google+ JavaScript API at https://developers.google.com/+/web/api/javascript. The documentation provides you with full coverage of using the API and provides links on how to set up a Google+ developer account and a Google+ application, which is required to use the API.
18.118.139.224