Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add responseType code and password with token refresh interval #147

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
115 changes: 80 additions & 35 deletions app/scripts/directives/oauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,27 @@ directives.directive('oauth', [
restrict: 'AE',
replace: true,
scope: {
site: '@', // (required) set the oauth server host (e.g. http://oauth.example.com)
clientId: '@', // (required) client id
redirectUri: '@', // (required) client redirect uri
responseType: '@', // (optional) response type, defaults to token (use 'token' for implicit flow and 'code' for authorization code flow
scope: '@', // (optional) scope
profileUri: '@', // (optional) user profile uri (e.g http://example.com/me)
template: '@', // (optional) template to render (e.g views/templates/default.html)
text: '@', // (optional) login text
authorizePath: '@', // (optional) authorization url
state: '@', // (optional) An arbitrary unique string created by your app to guard against Cross-site Request Forgery
storage: '@', // (optional) Store token in 'sessionStorage' or 'localStorage', defaults to 'sessionStorage'
nonce: '@', // (optional) Send nonce on auth request
// OpenID Connect extras, more details in id-token.js:
issuer: '@', // (optional for OpenID Connect) issuer of the id_token, should match the 'iss' claim in id_token payload
subject: '@', // (optional for OpenID Connect) subject of the id_token, should match the 'sub' claim in id_token payload
pubKey: '@', // (optional for OpenID Connect) the public key(RSA public key or X509 certificate in PEM format) to verify the signature
wellKnown: '@', // (optional for OpenID Connect) whether to load public key according to .well-known/openid-configuration endpoint
logoutPath: '@', // (optional) A url to go to at logout
sessionPath: '@' // (optional) A url to use to check the validity of the current token.
site: '@', // (required) set the oauth server host (e.g. http://oauth.example.com)
clientId: '@', // (required) client id
redirectUri: '@', // (required) client redirect uri
responseType: '@', // (optional) response type, defaults to token (use 'token' for implicit flow, 'code' for authorization code flow and 'password' for resource owner password
scope: '@', // (optional) scope
profileUri: '@', // (optional) user profile uri (e.g http://example.com/me)
template: '@', // (optional) template to render (e.g views/templates/default.html)
text: '@', // (optional) login text
authorizePath: '@', // (optional) authorization url
tokenPath: '@', // (optional) token url
state: '@', // (optional) An arbitrary unique string created by your app to guard against Cross-site Request Forgery
storage: '@', // (optional) Store token in 'sessionStorage' or 'localStorage', defaults to 'sessionStorage'
nonce: '@', // (optional) Send nonce on auth request
// OpenID Connect extras, more details in id-token.js:
issuer: '@', // (optional for OpenID Connect) issuer of the id_token, should match the 'iss' claim in id_token payload
subject: '@', // (optional for OpenID Connect) subject of the id_token, should match the 'sub' claim in id_token payload
pubKey: '@', // (optional for OpenID Connect) the public key(RSA public key or X509 certificate in PEM format) to verify the signature
wellKnown: '@', // (optional for OpenID Connect) whether to load public key according to .well-known/openid-configuration endpoint
logoutPath: '@', // (optional) A url to go to at logout
sessionPath: '@', // (optional) A url to use to check the validity of the current token.
disableCheckSession:'@' // (optional) can current token be checked ?
}
};

Expand All @@ -58,22 +60,29 @@ directives.directive('oauth', [
OidcConfig.load(scope) // loads OIDC configuration from .well-known/openid-configuration if necessary
.then(function() {
IdToken.set(scope);
AccessToken.set(scope); // sets the access token object (if existing, from fragment or session)
initProfile(scope); // gets the profile resource (if existing the access token)
initView(); // sets the view (logged in or out)
checkValidity(); // ensure the validity of the current token
AccessToken.set(scope).then(function () { // sets the access token object (if existing, from fragment or session)
})
["finally"](function () {
initProfile(scope); // gets the profile resource (if existing the access token)
initView(); // sets the view (logged in or out)
checkValidity(); // ensure the validity of the current token
});
});
};

var initAttributes = function() {
scope.authorizePath = scope.authorizePath || '/oauth/authorize';
scope.tokenPath = scope.tokenPath || '/oauth/token';
scope.template = scope.template || 'views/templates/default.html';
scope.responseType = scope.responseType || 'token';
scope.text = scope.text || 'Sign In';
scope.state = scope.state || undefined;
scope.scope = scope.scope || undefined;
scope.storage = scope.storage || 'sessionStorage';
scope.authorizePath = scope.authorizePath || '/oauth/authorize';
scope.tokenPath = scope.tokenPath || '/oauth/token';
scope.template = scope.template || 'views/templates/default.html';
scope.responseType = scope.responseType || 'token';
scope.text = scope.text || 'Sign In';
scope.state = scope.state || undefined;
scope.scope = scope.scope || undefined;
scope.storage = scope.storage || 'sessionStorage';
scope.disableCheckSession = scope.disableCheckSession || false;
scope.typedLogin = "";
scope.typedPassword = "";
scope.typedKeepConnection = false;
};

var compile = function() {
Expand All @@ -96,8 +105,8 @@ directives.directive('oauth', [
var initView = function () {
var token = AccessToken.get();

if (!token) {
return scope.login();
if (!token && scope.responseType !== "password") {
return expired();
} // without access token it's logged out, so we attempt to log in
if (AccessToken.expired()) {
return expired();
Expand All @@ -115,12 +124,43 @@ directives.directive('oauth', [
};

scope.logout = function () {
scope.typedLogin = "";
scope.typedPassword = "";
scope.typedKeepConnection = false;
Endpoint.logout();
$rootScope.$broadcast('oauth:loggedOut');
scope.show = 'logged-out';
AccessToken.destroy();
};

scope.checkPassword = function () {
$http({
method: "POST",
url: scope.site + scope.tokenPath,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {grant_type: "password", username: scope.typedLogin, password: scope.typedPassword, scope: scope.scope}
}).then(function (result) {
if (scope.typedKeepConnection) {
AccessToken.setTokenFromPassword(scope, result.data, scope.typedLogin, scope.typedPassword, scope.scope);
} else {
AccessToken.setTokenFromPassword(scope, result.data);
scope.typedLogin = "";
scope.typedPassword = "";
scope.typedKeepConnection = false;
}
scope.show = "logged-in";
}, function () {
$rootScope.$broadcast('oauth:denied');
});
};

scope.$on('oauth:expired',expired);
scope.$on('oauth:expired', expired);

// user is authorized
var authorized = function() {
Expand All @@ -129,9 +169,13 @@ directives.directive('oauth', [
};

var expired = function() {
$rootScope.$broadcast('oauth:expired');
scope.show = 'logged-out';
scope.logout();
};

scope.runExpired = function() {
expired();
};

// set the oauth directive to the denied status
var denied = function() {
Expand Down Expand Up @@ -165,6 +209,7 @@ directives.directive('oauth', [
scope.$on('$stateChangeSuccess', function () {
$timeout(refreshDirective);
});

};

return definition;
Expand Down
Loading