stormpath / stormpath-sdk-angularjs

User Management for AngularJS (1.x) applications
http://docs.stormpath.com/angularjs/sdk/
Apache License 2.0
165 stars 58 forks source link

Client API Basics + Social Login v2 #197

Closed the-overengineer closed 7 years ago

the-overengineer commented 7 years ago

Implements a client-slide OAuth2 workflow, with a generic interface for the actual storage of tokens.

This is a part of the Client API feature. When communicating with a remote API, the SDK will now use /oauth/token instead of /login, and /oauth/revoke instead of /logout (with POST requests). Additionally, it will take care of setting the proper Authorization header, as well as of removing and refreshing the token pair on certain OAuth2-standard-prescribed errors.

Once can test this by taking the URL from the application webConfig (https://<app-name>.apps.dev.stormpath.io at the time this was written), and registering it as the remote endpoint in a config block:

.config(function(STORMPATH_CONFIG) {
  STORMPATH_CONFIG.ENDPOINT_PREFIX = 'https://<app-name>.apps.dev.stormpath.io';
})

When the domain is different than the request origin, the OAuth routine will automatically kick in. The implementation expects the client to support the password and refresh_token grant types.

The tokens are stored in a fairly generic way. Concrete token store implementations are managed through name-object pairs via the TokenStoreManager service. While this introduces string keys, it allows for a fairly centralised management system for them. Implementations must obey a simple contract, documented in the changed code:

{
  put(key: string, value: any) : $q.promise(), // indication of success
  get(key: string) : $q.promise(value),
  remove(key: string) : $q.promise() // indication of success
}

This allows for both synchronous and asynchronous store implementations.

By default, a dependency-less LocalStorageTokenStore is provided, and set as the default token store mechanism. However, one can easily add their own token store (as documented in the ngdocs), as long as it satisfies the contract.

   angular.module('app')
     .run(['$q', 'TokenStoreManager', function($q, TokenStoreManager) {
       // Can also be provided by a service/factory for better code organisation
       var myStore = {
         data: {},
         get: function get(key) {
           return this.data[key] ? $q.resolve(this.data[key]) : $q.reject();
         },
         put: function put(key, value) {
           this.data[key] = value;
           return $q.resolve();
         },
         remove: function remove(key) {
           delete this.data[key];
           return $q.resolve();
         }
       };

       TokenStoreManager.registerTokenStore('basicStore', myStore);

       var alsoMyStore = TokenStoreManager.getTokenStore('basicStore');
     }]);

A similar wrapper can be written around $cookies, SecureStorage, or other similar libs. Once a storage type is registered, it can be set as either the default storage type for all token objects created in the future, or just a specific one, if that is desired for some reason.

angular.module('app')
.config(function(StormpathOAuthTokenProvider) {
  StormpathOAuthTokenProvider.setTokenStoreType('basicStore');
})
.run(function(StormpathOAuthToken) {
  // Originally uses basicStore
  StormpathOAuthToken.setTokenStoreType('cookies');
  // Now uses the cookies implementation, whatever that may be
  StormpathOAuthToken.removeToken(); // Removes  from cookies storage
});

Likewise implements Social Auth v2 on top of these changes. Social authentication now bases the login form and the very authentication process on the Social Auth Client API specification and its redirects. Adds support for the stormpath_token grant flow needed to exchange the social auth for tokens.

In addition to all this, some code was moved around because it was now required by multiple modules.

Fixes #46