Merge branch 'v1' of git.daplie.com:Daplie/oauth3.js into v1
This commit is contained in:
		
						commit
						4657fcdb12
					
				
							
								
								
									
										21
									
								
								.well-known/oauth3/callback.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.well-known/oauth3/callback.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  |     <head> | ||||||
|  |         <meta charset="utf-8"> | ||||||
|  |         <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||||
|  |         <title>Redirecting...</title> | ||||||
|  |         <style> | ||||||
|  |         body { | ||||||
|  |           background-color: #ffcccc; | ||||||
|  |         } | ||||||
|  |         </style> | ||||||
|  |     </head> | ||||||
|  |     <body> | ||||||
|  |         Redirecting... | ||||||
|  | 
 | ||||||
|  |         <!-- TODO permanently cache with appcache (or service worker?) --> | ||||||
|  |         <!-- TODO slim this all down to a single file --> | ||||||
|  |         <script src="/assets/org.oauth3/oauth3.core.js"></script> | ||||||
|  |         <script src="callback.js"></script> | ||||||
|  |     </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										66
									
								
								.well-known/oauth3/callback.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								.well-known/oauth3/callback.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | |||||||
|  | (function () { | ||||||
|  | 	"use strict"; | ||||||
|  | 
 | ||||||
|  | 	var loc = window.location; | ||||||
|  | 	var loginWinObj = window.OAUTH3_CORE.queryparse(loc.hash || loc.search); | ||||||
|  |   var prefix = "(" + window.location.hostname + ") [.well-known/oauth3/callback.html]"; | ||||||
|  | 
 | ||||||
|  |   if (loginWinObj.debug) { | ||||||
|  |     console.warn(prefix, "DEBUG MODE ENABLED. Automatic redirects disabled."); | ||||||
|  |   } | ||||||
|  |   // '--oauth3-callback-' prefix exist for security so that an attacker can't social engineer execution an arbitrary function
 | ||||||
|  |   // TODO finalize name of '--oauth3-callback-', this will be a defacto standard
 | ||||||
|  |   // TODO maybe call it 'self-xss-' or 'hack-my-account-' to discourage people from doing dumb things?
 | ||||||
|  | 	var callbackName = '--oauth3-callback-' + loginWinObj.state; | ||||||
|  | 
 | ||||||
|  | 	console.log(prefix, loc.href); | ||||||
|  | 	console.log('Parsed URL Obj: ', loginWinObj); | ||||||
|  | 	console.log('callbackName: ', callbackName); | ||||||
|  | 
 | ||||||
|  |   window.oauth3complete = function () { | ||||||
|  |     // The hacks that used to be necessary for this on iOS should no longer be necessary in iOS 9+
 | ||||||
|  |     // see https://bugs.chromium.org/p/chromium/issues/detail?id=136610 and https://crbug.com/423444
 | ||||||
|  |     // TODO Should we still create an abstraction for older versions?
 | ||||||
|  |     if (window.parent) { | ||||||
|  |       // iframe
 | ||||||
|  |       try { | ||||||
|  |         window.parent[callbackName](loginWinObj); | ||||||
|  |         return; | ||||||
|  |       } catch(e) { | ||||||
|  |         console.warn(e); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (window.opener) { | ||||||
|  |       try { | ||||||
|  |         window.opener[callbackName](loginWinObj); | ||||||
|  |         return; | ||||||
|  |       } catch(e) { | ||||||
|  |         console.warn(e); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     console.error("neither window.parent nor window.opener existed to complete callback"); | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |     // the caller should close (or signal to close) the window
 | ||||||
|  |     try { | ||||||
|  |       window.close(); | ||||||
|  |     } catch (err) { | ||||||
|  |       console.log('Error: ', err); | ||||||
|  |     } | ||||||
|  |     */ | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   if (!loginWinObj.debug) { | ||||||
|  |     window.oauth3complete(); | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     document.body.innerHTML = window.location.hostname + window.location.pathname | ||||||
|  |           + '<br/><br/>You\'ve passed the \'debug\' parameter so we\'re pausing' | ||||||
|  |           + ' to let you look at logs or whatever it is that you intended to do.' | ||||||
|  |           + '<br/><br/>Continue with callback: <a href="javascript:window.oauth3complete()">javascript:window.oauth3complete()</' + 'a>'; | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | }()); | ||||||
							
								
								
									
										0
									
								
								.well-known/oauth3/crossdomain.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.well-known/oauth3/crossdomain.html
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								.well-known/oauth3/crossdomain.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.well-known/oauth3/crossdomain.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										330
									
								
								.well-known/oauth3/directives.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								.well-known/oauth3/directives.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,330 @@ | |||||||
|  | (function () { | ||||||
|  |   'use strict'; | ||||||
|  | 
 | ||||||
|  |   console.log('[DAPLIE oauth3 directives.js]'); | ||||||
|  |   console.log(window.location); | ||||||
|  | 
 | ||||||
|  |   var iter = 0; | ||||||
|  | 
 | ||||||
|  |   function main() { | ||||||
|  | 
 | ||||||
|  |     var rpc = {}; | ||||||
|  |     //var myself = location.protocol + '//' + location.host + location.pathname;
 | ||||||
|  |     var incoming; | ||||||
|  |     var forwarding = {}; | ||||||
|  |     var err; | ||||||
|  |     var browserState; | ||||||
|  |     var browserCallback; | ||||||
|  |     var action; | ||||||
|  | 
 | ||||||
|  |     function parseParams() { | ||||||
|  |       var params = {}; | ||||||
|  | 
 | ||||||
|  |       function parseParamsString(str) { | ||||||
|  |         str.substr(1).split('&').filter(function (el) { return el; }).forEach(function (pair) { | ||||||
|  |           pair = pair.split('='); | ||||||
|  |           var key = decodeURIComponent(pair[0]); | ||||||
|  |           var val = decodeURIComponent(pair[1]); | ||||||
|  | 
 | ||||||
|  |           if (params[key]) { | ||||||
|  |             console.warn("overwriting key '" + key + "' '" + params[key] + "'"); | ||||||
|  |           } | ||||||
|  |           params[key] = val; | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       parseParamsString(window.location.search); | ||||||
|  |       // handle cases where hash is treated like it's own href
 | ||||||
|  |       // TODO /#/?search=blah
 | ||||||
|  |       parseParamsString(window.location.hash); | ||||||
|  | 
 | ||||||
|  |       return params; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function querystringify(params) { | ||||||
|  |       var arr = []; | ||||||
|  | 
 | ||||||
|  |       Object.keys(params).forEach(function (k) { | ||||||
|  |         arr.push(encodeURIComponent(k) + '=' + encodeURIComponent(params[k])); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       return arr.join('&'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function phoneAway(/*redirectURi, params*/) { | ||||||
|  |       // TODO test for ? / #
 | ||||||
|  |       window.location.href = incoming.redirect_uri + '#' + querystringify(forwarding); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function lintAndSetRedirectable(browserState, params) { | ||||||
|  |       if (!params.redirect_uri) { | ||||||
|  |         window.alert('redirect_uri not defined'); | ||||||
|  |         err = new Error('redirect_uri not defined'); | ||||||
|  |         console.error(err.message); | ||||||
|  |         console.warn(err.stack); | ||||||
|  |         params.redirect_uri = document.referer; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (!browserState) { | ||||||
|  |         forwarding.error = "E_NO_BROWSER_STATE"; | ||||||
|  |         forwarding.error_description = "you must specify a state parameter"; | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       localStorage.setItem('oauth3.states.' + browserState, JSON.stringify(params)); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function redirectCallback() { | ||||||
|  |       var redirect_uri = incoming.redirect_uri; | ||||||
|  |       forwarding.callback = browserState; | ||||||
|  |       forwarding.action = 'close'; | ||||||
|  | 
 | ||||||
|  |       var url = redirect_uri + '#' + querystringify(forwarding); | ||||||
|  | 
 | ||||||
|  |       console.log('[debug] redirect_uri + params:', url); | ||||||
|  |       window.location.href = url; | ||||||
|  |       setTimeout(function () { | ||||||
|  |         if (iter >= 3) { | ||||||
|  |           console.log("dancing way too much... stopping now"); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |         iter += 1; | ||||||
|  |         console.log("I'm dancing by myse-e-elf"); | ||||||
|  |         // in case I'm redirecting to myself
 | ||||||
|  |         main(); | ||||||
|  |       }, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     rpc = {}; | ||||||
|  | 
 | ||||||
|  |     // Act as a provider and log the user out
 | ||||||
|  |     rpc.logout = function (browserState, incoming) { | ||||||
|  |       var url; | ||||||
|  |       if (!lintAndSetRedirectable(browserState, incoming)) { | ||||||
|  |         // TODO fail
 | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       localStorage.setItem('oauth3.states.' + browserState, JSON.stringify(incoming)); | ||||||
|  |       url = '/#/logout/' + browserState; | ||||||
|  | 
 | ||||||
|  |       // TODO specify specific account or all?
 | ||||||
|  |       window.location.href = url; | ||||||
|  |       setTimeout(function () { | ||||||
|  |         // in case I'm redirecting to myself
 | ||||||
|  |         main(); | ||||||
|  |       }, 0); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // Act as a provider and inform the consumer the logout is complete
 | ||||||
|  |     rpc.logout_callback = function (browserState/*, incoming*/) { | ||||||
|  |       // TODO pass redirect_uri and state through here so we can avoid localStorage
 | ||||||
|  |       var forwarding = {}; | ||||||
|  |       var originalRequest; | ||||||
|  | 
 | ||||||
|  |       if (!browserState) { | ||||||
|  |         forwarding.error = "E_NO_BROWSER_STATE"; | ||||||
|  |         forwarding.error_description = "you must specify a state parameter"; | ||||||
|  |         if (incoming.redirect_uri) { | ||||||
|  |           phoneAway(incoming.redirect_uri, forwarding); | ||||||
|  |         } | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       originalRequest = JSON.parse(localStorage.getItem('oauth3.states.' + browserState)); | ||||||
|  |       forwarding.action = 'close'; | ||||||
|  |       forwarding.state = browserState; | ||||||
|  |       //phoneAway(originalRequest.redirect_uri, forwarding);
 | ||||||
|  |       window.location.href = originalRequest.redirect_uri + '#' + querystringify(forwarding); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     rpc.directives = function (browserState, incoming) { | ||||||
|  |       if (!lintAndSetRedirectable(browserState, incoming)) { | ||||||
|  |         phoneAway(); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var updatedAt = new Date(localStorage.getItem('oauth3.directives.updated_at')).valueOf(); | ||||||
|  |       var fresh = (Date.now() - updatedAt) < (24 * 60 * 60 * 1000); | ||||||
|  |       var directives = localStorage.getItem('oauth3.directives'); | ||||||
|  |       var redirected = false; | ||||||
|  | 
 | ||||||
|  |       function redirectIf() { | ||||||
|  |         if (redirected) { | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         redirected = true; | ||||||
|  |         redirectCallback(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (directives) { | ||||||
|  |         forwarding.directives = directives; | ||||||
|  |         redirectIf(); | ||||||
|  |         if (fresh) { | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var req = new XMLHttpRequest(); | ||||||
|  |       req.open('GET', '.well-known/oauth3.json', true); | ||||||
|  |       req.addEventListener('readystatechange', function () { | ||||||
|  |         if (4 !== req.readyState) { | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (200 !== req.status) { | ||||||
|  |           forwarding.error = "E_STATUS_" + req.status; | ||||||
|  |           forwarding.error_description = "expected 200 OK json or text response for oauth3.json but got '" + req.status + "'"; | ||||||
|  |           redirectIf(); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |           directives = btoa(JSON.stringify(JSON.parse(req.responseText))); | ||||||
|  |           forwarding.directives = directives; | ||||||
|  |           forwarding.callback = browserState; | ||||||
|  |           localStorage.setItem('oauth3.directives', directives); | ||||||
|  |           localStorage.setItem('oauth3.directives.updated_at', new Date().toISOString()); | ||||||
|  |         } catch(e) { | ||||||
|  |           forwarding.error = "E_PARSE_JSON"; | ||||||
|  |           forwarding.error_description = e.message; | ||||||
|  |           console.error(forwarding.error); | ||||||
|  |           console.error(forwarding.error_description); | ||||||
|  |           console.error(req.responseText); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         redirectIf(); | ||||||
|  |       }); | ||||||
|  |       req.send(); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // the provider is contacting me
 | ||||||
|  |     rpc.close = function (browserState, incoming) { | ||||||
|  |       incoming.callback = browserState; | ||||||
|  |       catchAll(); | ||||||
|  |     }; | ||||||
|  |     // the provider is contacting me
 | ||||||
|  |     rpc.redirect = function (/*browserState, incoming*/) { | ||||||
|  |       catchAll(); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     function catchAll() { | ||||||
|  |       function phoneHome() { | ||||||
|  |         if (browserCallback === 'completeLogin') { | ||||||
|  |           // Deprecated
 | ||||||
|  |           console.log('[deprecated] callback completeLogin'); | ||||||
|  |           (window.opener||window.parent).completeLogin(null, null, incoming); | ||||||
|  |         } else { | ||||||
|  |           console.log('[DEBUG] I would be closed by my parent now'); | ||||||
|  |           console.log('__oauth3_' + browserCallback); | ||||||
|  |           console.log(window.opener && window.opener['__oauth3_' + browserCallback]); | ||||||
|  |           console.log(window.parent && window.parent['__oauth3_' + browserCallback]); | ||||||
|  |           console.log(incoming); | ||||||
|  |           (window.opener||window.parent)['__oauth3_' + browserCallback](incoming); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (!(incoming.browser_state || incoming.state)) { | ||||||
|  |         window.alert("callback URLs should include 'browser_state' (authorization code)" | ||||||
|  |           + " or 'state' (implicit grant))"); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       setTimeout(function () { | ||||||
|  |         // opener is for popup window, new tab
 | ||||||
|  |         // parent is for iframe
 | ||||||
|  |         phoneHome(); | ||||||
|  |       }, 10); | ||||||
|  | 
 | ||||||
|  |       // iOS Webview (namely Chrome) workaround
 | ||||||
|  |       setTimeout(function () { | ||||||
|  |         console.log('I would close now'); | ||||||
|  |         // XXX OAUTH3 DEBUG FRAME XXX // make this easy to find
 | ||||||
|  |         window.open('', '_self', ''); | ||||||
|  |         window.close(); | ||||||
|  |       }, 50); | ||||||
|  | 
 | ||||||
|  |       setTimeout(function () { | ||||||
|  |         var i; | ||||||
|  |         var len = localStorage.length; | ||||||
|  |         var key; | ||||||
|  |         var json; | ||||||
|  |         var fresh; | ||||||
|  | 
 | ||||||
|  |         for (i = 0; i < len; i += 1) { | ||||||
|  |           key = localStorage.key(i); | ||||||
|  |           // TODO check updatedAt
 | ||||||
|  |           if (/^oauth3\./.test(key)) { | ||||||
|  |             try { | ||||||
|  |               json = localStorage.getItem(key); | ||||||
|  |               if (json) { | ||||||
|  |                 json = JSON.parse(json); | ||||||
|  |               } | ||||||
|  |             } catch (e) { | ||||||
|  |               // ignore
 | ||||||
|  |               json = null; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             fresh = json && (Date.now() - json.updatedAt < (5 * 60 * 1000)); | ||||||
|  | 
 | ||||||
|  |             if (!fresh) { | ||||||
|  |               localStorage.removeItem(key); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         forwarding.updatedAt = Date.now(); | ||||||
|  |         localStorage.setItem('oauth3.' + (forwarding.browser_state || forwarding.state), JSON.stringify(forwarding)); | ||||||
|  |       }, 0); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function parseAction(params) { | ||||||
|  |       if (params.action) { | ||||||
|  |         return params.action; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (params.close) { | ||||||
|  |         return 'close'; | ||||||
|  |       } | ||||||
|  |       if (params.logout_callback) { | ||||||
|  |         return 'logout_callback'; | ||||||
|  |       } | ||||||
|  |       if (params.logout) { | ||||||
|  |         return 'logout'; | ||||||
|  |       } | ||||||
|  |       if (params.callback) { | ||||||
|  |         return 'close'; | ||||||
|  |       } | ||||||
|  |       if (params.directives) { | ||||||
|  |         return 'directives'; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return 'redirect'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     incoming = parseParams(); | ||||||
|  |     browserState = incoming.browser_state || incoming.state; | ||||||
|  |     action = parseAction(incoming); | ||||||
|  |     forwarding.url = window.location.href; | ||||||
|  |     forwarding.browser_state = browserState; | ||||||
|  |     forwarding.state = browserState; | ||||||
|  | 
 | ||||||
|  |     if (!incoming.provider_uri) { | ||||||
|  |       browserCallback = incoming.callback || browserState; | ||||||
|  |     } else { | ||||||
|  |       // deprecated
 | ||||||
|  |       browserCallback = 'completeLogin'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     console.log('[debug]', action, incoming); | ||||||
|  | 
 | ||||||
|  |     if (rpc[action]) { | ||||||
|  |       rpc[action](browserState, incoming); | ||||||
|  |     } else { | ||||||
|  |       window.alert('unsupported action'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   main(); | ||||||
|  | }()); | ||||||
							
								
								
									
										9
									
								
								.well-known/oauth3/directives.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.well-known/oauth3/directives.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | { "authorization_dialog": { "url": "#/authorization_dialog" } | ||||||
|  | , "access_token": { "method": "POST", "url": "api/org.oauth3.provider/access_token" } | ||||||
|  | , "otp": { "method": "POST" , "url": "api/org.oauth3.provider/otp" } | ||||||
|  | , "credential_otp": { "method": "POST" , "url": "api/org.oauth3.provider/otp" } | ||||||
|  | , "credential_meta": { "url": "api/org.oauth3.provider/logins/meta/:type/:id" } | ||||||
|  | , "credential_create": { "method": "POST" , "url": "api/org.oauth3.provider/logins" } | ||||||
|  | , "grants": { "method": "GET", "url": "api/org.oauth3.provider/grants/:azp/:sub" } | ||||||
|  | , "authorization_decision": { "method": "POST", "url": "api/org.oauth3.provider/authorization_decision" } | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								.well-known/oauth3/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								.well-known/oauth3/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  |   <head> | ||||||
|  |     <style> | ||||||
|  |       body { | ||||||
|  |         background-color: #ffcccc; | ||||||
|  |       } | ||||||
|  |     </style> | ||||||
|  |   </head> | ||||||
|  |   <body> | ||||||
|  |   OAuth3 RPC | ||||||
|  | 
 | ||||||
|  |   <script src="/assets/com.jquery/jquery-3.1.1.js"></script> | ||||||
|  |   <script src="/assets/org.oauth3/oauth3.core.js"></script> | ||||||
|  |   <script> | ||||||
|  |     'use strict'; | ||||||
|  | 
 | ||||||
|  |     // TODO what about search within hash? | ||||||
|  |     var prefix = "(" + window.location.hostname + ") [.well-known/oauth3/]"; | ||||||
|  |     var params = OAUTH3_CORE.queryparse(window.location.hash || window.location.search); | ||||||
|  |     if (params.debug) { | ||||||
|  |       console.warn(prefix, "DEBUG MODE ENABLED. Automatic redirects disabled."); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     console.log(prefix, 'hash||search:'); | ||||||
|  |     console.log(window.location.hash || window.location.search); | ||||||
|  | 
 | ||||||
|  |     console.log(prefix, 'params:'); | ||||||
|  |     console.log(params); | ||||||
|  | 
 | ||||||
|  |     $.ajax({ url: 'directives.json' }).then(function (resp) { | ||||||
|  |       var b64 = btoa(JSON.stringify(resp, null, 0)) | ||||||
|  |       var urlsafe64 = OAUTH3_CORE.utils.base64ToUrlSafeBase64(b64); | ||||||
|  |       var redirect; | ||||||
|  | 
 | ||||||
|  |       console.log(prefix, 'directives'); | ||||||
|  |       console.log(resp); | ||||||
|  | 
 | ||||||
|  |       console.log(prefix, 'base64'); | ||||||
|  |       console.log(urlsafe64); | ||||||
|  | 
 | ||||||
|  |       // TODO try postMessage back to redirect_uri domain right here | ||||||
|  |       // window.postMessage(); | ||||||
|  | 
 | ||||||
|  |       // TODO make sure it's https NOT http | ||||||
|  |       // NOTE: this can be only up to 2,083 characters | ||||||
|  |       console.log(prefix, 'params.redirect_uri:', params.redirect_uri); | ||||||
|  |       redirect = params.redirect_uri + '?' + OAUTH3_CORE.querystringify({ | ||||||
|  |         state: params.state | ||||||
|  |       , directives: urlsafe64 | ||||||
|  |       , debug: params.debug || undefined | ||||||
|  |       }) | ||||||
|  | 
 | ||||||
|  |       console.log(prefix, 'redirect'); | ||||||
|  |       console.log(redirect); | ||||||
|  |       if (!params.debug) { | ||||||
|  |         window.location = redirect; | ||||||
|  |       } else { | ||||||
|  |         // yes, we're violating the security lint with purpose | ||||||
|  |         document.body.innerHTML += window.location.host + window.location.pathname | ||||||
|  |           + '<br/><br/>You\'ve passed the \'debug\' parameter so we\'re pausing' | ||||||
|  |           + ' to let you look at logs or whatever it is that you intended to do.' | ||||||
|  |           + '<br/><br/>Continue with redirect: <a href="' + redirect + '">' + redirect + '</' + 'a>'; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   </script> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										0
									
								
								.well-known/oauth3/logout.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.well-known/oauth3/logout.html
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								.well-known/oauth3/logout.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.well-known/oauth3/logout.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										101
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								README.md
									
									
									
									
									
								
							| @ -1,6 +1,88 @@ | |||||||
| oauth3.js | oauth3.js | ||||||
| ========= | ========= | ||||||
| 
 | 
 | ||||||
|  | The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation | ||||||
|  | (Yes! works in browsers and node.js with no extra dependencies or bloat and no hacks!) | ||||||
|  | 
 | ||||||
|  | Instead of bloating your webapp and ruining the mobile experience, | ||||||
|  | you can use a single, small javascript file for all OAuth3 providers | ||||||
|  | (and almost all OAuth2 providers) with a seemless experience. | ||||||
|  | 
 | ||||||
|  | Also, instead of complicated (or worse - insecure) CLI and Desktop login methods, | ||||||
|  | you can easily integrate an OAuth3 flow (or broker) into any node.js app (i.e. Electron, Node-Webkit) | ||||||
|  | with 0 pain. | ||||||
|  | 
 | ||||||
|  | Installation | ||||||
|  | ------------ | ||||||
|  | 
 | ||||||
|  | **Easy Install** for Web Apps (including Mobile): | ||||||
|  | 
 | ||||||
|  | 1. In your web site / web app folder create a folder called `assets` | ||||||
|  | 2. Inside of `assets` create another folder called `org.oauth3` | ||||||
|  | 3. Download [oauth.js-v1.zip](https://git.daplie.com/Daplie/oauth3.js/repository/archive.zip?ref=v1) | ||||||
|  | 4. Double-click to unzip the folder. | ||||||
|  | 5. Copy `oauth3.js` and `oauth3.browser.js` to `assets/org.oauth3` | ||||||
|  | 
 | ||||||
|  | **Advanced Installation with `git`** | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | # Navigate to your web site or web app | ||||||
|  | pushd /path/to/your/web/app | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # clone the project as assets/org.oauth3 | ||||||
|  | mkdir -p assets | ||||||
|  | git clone git@git.daplie.com:Daplie/oauth3.js.git assets/org.oauth3 | ||||||
|  | pushd assests/org.oauth3 | ||||||
|  | git checkout v1 | ||||||
|  | popd | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # symlink `.well-known/oauth3` to `assets/org.oauth3/.well-known/oauth3` | ||||||
|  | mkdir -p .well-known | ||||||
|  | ln -sf  ../assets/org.oauth3/.well-known/oauth3 .well-known/oauth3 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | **Advanced Installation with `bower`** | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | # Install to bower_components | ||||||
|  | bower install oauth3 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # create a `.well-known` folder and an `assets` folder | ||||||
|  | mkdir -p .well-known assets | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # symlink `.well-known/oauth3` to `bower_components/oauth3/.well-known/oauth3` | ||||||
|  | ln -sf  ../bower_components/oauth3/.well-known/oauth3 .well-known/oauth3 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # symlink `assets/org.oauth3` to `bower_components/oauth3` | ||||||
|  | ln -sf  ../bower_components/oauth3/.well-known/oauth3 .well-known/oauth3 | ||||||
|  | ln -sf  ../bower_components/oauth3 assets/org.oauth3 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Usage | ||||||
|  | ----- | ||||||
|  | 
 | ||||||
|  | Update your HTML to include the the following script tags: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | <script src="assets/org.oauth3/oauth3.js"></script> | ||||||
|  | <script src="assets/org.oauth3/oauth3.browser.js"></script> | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | If you use jQuery you should also include | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | <script src="assets/org.oauth3/oauth3.jquery.js"></script> | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Stable API | ||||||
|  | ---------- | ||||||
|  | 
 | ||||||
| Public utilities for browser and node.js: | Public utilities for browser and node.js: | ||||||
| 
 | 
 | ||||||
| * `querystringify(query)` | * `querystringify(query)` | ||||||
| @ -14,6 +96,25 @@ URL generation: | |||||||
| * `loginCode` | * `loginCode` | ||||||
| * `resourceOwnerPassword` | * `resourceOwnerPassword` | ||||||
| 
 | 
 | ||||||
|  | Roadmap | ||||||
|  | ------- | ||||||
|  | 
 | ||||||
|  | * v1.0 - "implicit grant" authorization with examples | ||||||
|  |   * popup | ||||||
|  |   * iframe | ||||||
|  |   * documentation | ||||||
|  | * v1.1 - cleanup | ||||||
|  |   * in-flow discovery | ||||||
|  |   * smallest possible size | ||||||
|  |   * inline windowing (non-promisable callback) | ||||||
|  |   * async set/get | ||||||
|  |   * logout | ||||||
|  | * v1.2 - features | ||||||
|  |   * "authorization code" flow | ||||||
|  |   * "broker" flow | ||||||
|  | * v1.3 - features | ||||||
|  |   * remove grants | ||||||
|  | 
 | ||||||
| URI vs URL | URI vs URL | ||||||
| ---------- | ---------- | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -13,7 +13,8 @@ | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   var browser = exports.OAUTH3_BROWSER = { |   var browser = exports.OAUTH3_BROWSER = { | ||||||
|     clientUri: function (location) { |     window: window | ||||||
|  |   , clientUri: function (location) { | ||||||
|       return OAUTH3_CORE.normalizeUri(location.host + location.pathname); |       return OAUTH3_CORE.normalizeUri(location.host + location.pathname); | ||||||
|     } |     } | ||||||
|   , discover: function (providerUri, opts) { |   , discover: function (providerUri, opts) { | ||||||
| @ -118,18 +119,36 @@ | |||||||
|             resolve(tokens); |             resolve(tokens); | ||||||
|           }; |           }; | ||||||
|         }); |         }); | ||||||
|  |       }).then(function (tokens) { | ||||||
|  |         return OAUTH3.hooks.refreshSession( | ||||||
|  |           opts.session || { | ||||||
|  |             provider_uri: providerUri | ||||||
|  |           , client_id: opts.client_id | ||||||
|  |           , client_uri: opts.client_uri || opts.clientUri | ||||||
|  |           } | ||||||
|  |         , tokens | ||||||
|  |         ); | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   , frameRequest: function (url, state, opts) { |   , frameRequest: function (url, state, opts) { | ||||||
|       var promise; |       var promise; | ||||||
| 
 | 
 | ||||||
|       if ('background' === opts.type) { |       if (!opts.windowType) { | ||||||
|  |         opts.windowType = 'popup'; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ('background' === opts.windowType) { | ||||||
|         promise = browser.insertIframe(url, state, opts); |         promise = browser.insertIframe(url, state, opts); | ||||||
|       } else if ('popup' === opts.type) { |       } else if ('popup' === opts.windowType) { | ||||||
|         promise = browser.openWindow(url, state, opts); |         promise = browser.openWindow(url, state, opts); | ||||||
|  |       } else if ('inline' === opts.windowType) { | ||||||
|  |         // callback function will never execute and would need to redirect back to current page
 | ||||||
|  |         // rather than the callback.html
 | ||||||
|  |         url += '&original_url=' + browser.window.location.href; | ||||||
|  |         promise = browser.window.location = url; | ||||||
|       } else { |       } else { | ||||||
|         throw new Error("login framing method not specified or not type yet implemented"); |         throw new Error("login framing method options.windowType not specified or not type yet implemented"); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       return promise.then(function (params) { |       return promise.then(function (params) { | ||||||
| @ -245,7 +264,7 @@ | |||||||
|     //
 |     //
 | ||||||
|     // Logins
 |     // Logins
 | ||||||
|     //
 |     //
 | ||||||
|   , requests: { |   , authn: { | ||||||
|       authorizationRedirect: function (providerUri, opts) { |       authorizationRedirect: function (providerUri, opts) { | ||||||
|         // TODO get own directives
 |         // TODO get own directives
 | ||||||
| 
 | 
 | ||||||
| @ -260,9 +279,19 @@ | |||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           return browser.frameRequest(prequest.url, prequest.state, opts); |           return browser.frameRequest(prequest.url, prequest.state, opts); | ||||||
|  |         }).then(function (tokens) { | ||||||
|  |           return OAUTH3.hooks.refreshSession( | ||||||
|  |             opts.session || { | ||||||
|  |               provider_uri: providerUri | ||||||
|  |             , client_id: opts.client_id | ||||||
|  |             , client_uri: opts.client_uri || opts.clientUri | ||||||
|  |             } | ||||||
|  |           , tokens | ||||||
|  |           ); | ||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|     , implicitGrant: function (providerUri, opts) { |     , implicitGrant: function (providerUri, opts) { | ||||||
|  |         // TODO let broker=true change behavior to open discover inline with frameRequest
 | ||||||
|         // TODO OAuth3 provider should use the redirect URI as the appId?
 |         // TODO OAuth3 provider should use the redirect URI as the appId?
 | ||||||
|         return OAUTH3.discover(providerUri, opts).then(function (directive) { |         return OAUTH3.discover(providerUri, opts).then(function (directive) { | ||||||
|           var prequest = OAUTH3_CORE.urls.implicitGrant( |           var prequest = OAUTH3_CORE.urls.implicitGrant( | ||||||
| @ -276,6 +305,15 @@ | |||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           return browser.frameRequest(prequest.url, prequest.state, opts); |           return browser.frameRequest(prequest.url, prequest.state, opts); | ||||||
|  |         }).then(function (tokens) { | ||||||
|  |           return OAUTH3.hooks.refreshSession( | ||||||
|  |             opts.session || { | ||||||
|  |               provider_uri: providerUri | ||||||
|  |             , client_id: opts.client_id | ||||||
|  |             , client_uri: opts.client_uri || opts.clientUri | ||||||
|  |             } | ||||||
|  |           , tokens | ||||||
|  |           ); | ||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|     , logout: function (providerUri, opts) { |     , logout: function (providerUri, opts) { | ||||||
| @ -455,14 +493,14 @@ | |||||||
| 
 | 
 | ||||||
|         , code: data.code |         , code: data.code | ||||||
| 
 | 
 | ||||||
|         , access_token: data.accessToken |         , access_token: data.access_token | ||||||
|         , expires_at: data.expiresAt |         , expires_at: data.expires_at | ||||||
|         , expires_in: data.expiresIn |         , expires_in: data.expires_in | ||||||
|         , scope: data.scope |         , scope: data.scope | ||||||
| 
 | 
 | ||||||
|         , refresh_token: data.refreshToken |         , refresh_token: data.refresh_token | ||||||
|         , refresh_expires_at: data.refreshExpiresAt |         , refresh_expires_at: data.refresh_expires_at | ||||||
|         , refresh_expires_in: data.refreshExpiresIn |         , refresh_expires_in: data.refresh_expires_in | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         if ('token' === scope.appQuery.response_type) { |         if ('token' === scope.appQuery.response_type) { | ||||||
| @ -507,6 +545,7 @@ | |||||||
|       }, 50); |       }, 50); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |   browser.requests = browser.authn; | ||||||
| 
 | 
 | ||||||
|   Object.keys(browser).forEach(function (key) { |   Object.keys(browser).forEach(function (key) { | ||||||
|     if ('requests' === key) { |     if ('requests' === key) { | ||||||
|  | |||||||
| @ -175,10 +175,10 @@ | |||||||
|       , signature: parts[2] // should remain url-safe base64
 |       , signature: parts[2] // should remain url-safe base64
 | ||||||
|       }; |       }; | ||||||
|     } |     } | ||||||
|   , getFreshness: function (meta, staletime, now) { |   , getFreshness: function (tokenMeta, staletime, now) { | ||||||
|       staletime = staletime || (15 * 60); |       staletime = staletime || (15 * 60); | ||||||
|       now = now || Date.now(); |       now = now || Date.now(); | ||||||
|       var fresh = ((parseInt(meta.exp, 10) || 0) - Math.round(now / 1000)); |       var fresh = ((parseInt(tokenMeta.exp, 10) || 0) - Math.round(now / 1000)); | ||||||
| 
 | 
 | ||||||
|       if (fresh >= staletime) { |       if (fresh >= staletime) { | ||||||
|         return 'fresh'; |         return 'fresh'; | ||||||
|  | |||||||
| @ -158,7 +158,7 @@ | |||||||
| 
 | 
 | ||||||
|     var url = core.urls.resolve(directive.issuer, directive.grants.url) |     var url = core.urls.resolve(directive.issuer, directive.grants.url) | ||||||
|       .replace(/(:azp|:client_id)/g, core.normalizeUri(opts.client_id || opts.client_uri)) |       .replace(/(:azp|:client_id)/g, core.normalizeUri(opts.client_id || opts.client_uri)) | ||||||
|       .replace(/(:sub|:account_id)/g, opts.session.meta.sub) |       .replace(/(:sub|:account_id)/g, opts.session.token.sub) | ||||||
|       ; |       ; | ||||||
|     var data = { |     var data = { | ||||||
|       client_id: opts.client_id |       client_id: opts.client_id | ||||||
| @ -206,12 +206,14 @@ | |||||||
| 
 | 
 | ||||||
|     //$('.js-user-avatar').attr('src', userAvatar);
 |     //$('.js-user-avatar').attr('src', userAvatar);
 | ||||||
| 
 | 
 | ||||||
|  |     /* | ||||||
|     console.log('grants options'); |     console.log('grants options'); | ||||||
|     console.log(loc.hash); |     console.log(loc.hash); | ||||||
|     console.log(loc.search); |     console.log(loc.search); | ||||||
|     console.log(clientObj); |     console.log(clientObj); | ||||||
|     console.log(session.meta); |     console.log(session.token); | ||||||
|     console.log(window.document.referrer); |     console.log(window.document.referrer); | ||||||
|  |     */ | ||||||
| 
 | 
 | ||||||
|     return OAUTH3.requests.grants(CONFIG.host, { |     return OAUTH3.requests.grants(CONFIG.host, { | ||||||
|       method: 'GET' |       method: 'GET' | ||||||
| @ -231,7 +233,7 @@ | |||||||
|       console.log(grantResults); |       console.log(grantResults); | ||||||
| 
 | 
 | ||||||
|       if (grantResults.data.error) { |       if (grantResults.data.error) { | ||||||
|         window.alert('grantResults: ' + grantResults.data.errorDescription || grantResults.data.error.message); |         window.alert('grantResults: ' + grantResults.data.error_description || grantResults.data.error.message); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
| @ -256,7 +258,7 @@ | |||||||
|         //return generateToken(session, clientObj);
 |         //return generateToken(session, clientObj);
 | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       grants = grantResults.originalData.grants.filter(function (grant) { |       grants = (grantResults.originalData||grantResults.data).grants.filter(function (grant) { | ||||||
|         if (clientUri === (grant.azp || grant.oauth_client_id || grant.oauthClientId)) { |         if (clientUri === (grant.azp || grant.oauth_client_id || grant.oauthClientId)) { | ||||||
|           return true; |           return true; | ||||||
|         } |         } | ||||||
|  | |||||||
							
								
								
									
										29
									
								
								oauth3.js
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								oauth3.js
									
									
									
									
									
								
							| @ -27,6 +27,7 @@ | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   // TODO move recase out
 |   // TODO move recase out
 | ||||||
|  |   /* | ||||||
|   oauth3._recaseRequest = function (recase, req) { |   oauth3._recaseRequest = function (recase, req) { | ||||||
|     // convert JavaScript camelCase to oauth3/ruby snake_case
 |     // convert JavaScript camelCase to oauth3/ruby snake_case
 | ||||||
|     if (req.data && 'object' === typeof req.data) { |     if (req.data && 'object' === typeof req.data) { | ||||||
| @ -44,6 +45,7 @@ | |||||||
|     } |     } | ||||||
|     return resp; |     return resp; | ||||||
|   }; |   }; | ||||||
|  |   */ | ||||||
| 
 | 
 | ||||||
|   oauth3.hooks = { |   oauth3.hooks = { | ||||||
|     checkSession: function (preq, opts) { |     checkSession: function (preq, opts) { | ||||||
| @ -51,7 +53,7 @@ | |||||||
|         console.warn('[oauth3.hooks.checkSession] no session'); |         console.warn('[oauth3.hooks.checkSession] no session'); | ||||||
|         return oauth3.PromiseA.resolve(null); |         return oauth3.PromiseA.resolve(null); | ||||||
|       } |       } | ||||||
|       var freshness = oauth3.core.jwt.getFreshness(preq.session.meta, opts.staletime); |       var freshness = oauth3.core.jwt.getFreshness(preq.session.token, opts.staletime); | ||||||
|       console.info('[oauth3.hooks.checkSession] freshness', freshness, preq.session); |       console.info('[oauth3.hooks.checkSession] freshness', freshness, preq.session); | ||||||
| 
 | 
 | ||||||
|       switch (freshness) { |       switch (freshness) { | ||||||
| @ -118,11 +120,11 @@ | |||||||
|       oldSession.client_uri = clientUri;      // azp
 |       oldSession.client_uri = clientUri;      // azp
 | ||||||
| 
 | 
 | ||||||
|       // info about the newly-discovered token
 |       // info about the newly-discovered token
 | ||||||
|       oldSession.meta = core.jwt.decode(oldSession.access_token).payload; |       oldSession.token = oldSession.meta = core.jwt.decode(oldSession.access_token).payload; | ||||||
| 
 | 
 | ||||||
|       oldSession.meta.sub = oldSession.meta.sub || oldSession.meta.acx.id; |       oldSession.token.sub = oldSession.token.sub || oldSession.token.acx.id; | ||||||
|       oldSession.meta.client_uri = clientUri; |       oldSession.token.client_uri = clientUri; | ||||||
|       oldSession.meta.provider_uri = providerUri; |       oldSession.token.provider_uri = providerUri; | ||||||
| 
 | 
 | ||||||
|       if (oldSession.refresh_token || oldSession.refreshToken) { |       if (oldSession.refresh_token || oldSession.refreshToken) { | ||||||
|         oldSession.refresh = core.jwt.decode(oldSession.refresh_token || oldSession.refreshToken).payload; |         oldSession.refresh = core.jwt.decode(oldSession.refresh_token || oldSession.refreshToken).payload; | ||||||
| @ -193,14 +195,14 @@ | |||||||
|   // TODO simplify (nix recase)
 |   // TODO simplify (nix recase)
 | ||||||
|   oauth3.provideRequest = function (rawRequest, opts) { |   oauth3.provideRequest = function (rawRequest, opts) { | ||||||
|     opts = opts || {}; |     opts = opts || {}; | ||||||
|     var Recase = exports.Recase || require('recase'); |     //var Recase = exports.Recase || require('recase');
 | ||||||
|     // TODO make insensitive to providing exceptions
 |     // TODO make insensitive to providing exceptions
 | ||||||
|     var recase = Recase.create({ exceptions: {} }); |     //var recase = Recase.create({ exceptions: {} });
 | ||||||
| 
 | 
 | ||||||
|     function lintAndRequest(preq) { |     function lintAndRequest(preq) { | ||||||
|       function goGetHer() { |       function goGetHer() { | ||||||
|         if (preq.session) { |         if (preq.session) { | ||||||
|           // TODO check session.meta.aud against preq.url to make sure they match
 |           // TODO check session.token.aud against preq.url to make sure they match
 | ||||||
|           console.warn("[security] session audience checking has not been implemented yet (it's up to you to check)"); |           console.warn("[security] session audience checking has not been implemented yet (it's up to you to check)"); | ||||||
|           preq.headers = preq.headers || {}; |           preq.headers = preq.headers || {}; | ||||||
|           preq.headers.Authorization = 'Bearer ' + (preq.session.access_token || preq.session.accessToken); |           preq.headers.Authorization = 'Bearer ' + (preq.session.access_token || preq.session.accessToken); | ||||||
| @ -236,9 +238,10 @@ | |||||||
|         return lintAndRequest(req, opts); |         return lintAndRequest(req, opts); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       req = oauth3._recaseRequest(recase, req); |       //req = oauth3._recaseRequest(recase, req);
 | ||||||
|       return lintAndRequest(req, opts).then(function (res) { |       return lintAndRequest(req, opts).then(function (res) { | ||||||
|         return oauth3._recaseResponse(recase, res); |         //return oauth3._recaseResponse(recase, res);
 | ||||||
|  |         return res; | ||||||
|       }); |       }); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @ -285,7 +288,7 @@ | |||||||
| 
 | 
 | ||||||
|         return { |         return { | ||||||
|           client: oauth3.hooks.getGrants(opts.client_id + '-client') |           client: oauth3.hooks.getGrants(opts.client_id + '-client') | ||||||
|         , grants: oauth3.hooks.getGrants(opts.client_id) |         , grants: oauth3.hooks.getGrants(opts.client_id) || [] | ||||||
|         }; |         }; | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
| @ -295,10 +298,10 @@ | |||||||
|       var prequest = core.urls.loginCode(directive, opts); |       var prequest = core.urls.loginCode(directive, opts); | ||||||
| 
 | 
 | ||||||
|       return oauth3.request(prequest).then(function (res) { |       return oauth3.request(prequest).then(function (res) { | ||||||
|         // result = { uuid, expiresAt }
 |         // result = { uuid, expires_at }
 | ||||||
|         return { |         return { | ||||||
|           otpUuid: res.data.uuid |           otpUuid: res.data.uuid | ||||||
|         , otpExpires: res.data.expiresAt |         , otpExpires: res.data.expires_at | ||||||
|         }; |         }; | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -47,6 +47,9 @@ | |||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |       console.warn("What are grants? Baby don't hurt me. Don't hurt me. No more."); | ||||||
|  |       console.warn(grants); | ||||||
|  | 
 | ||||||
|       myGrants = grants.grants.filter(function (grant) { |       myGrants = grants.grants.filter(function (grant) { | ||||||
|         if (clientUri === (grant.azp || grant.oauth_client_id || grant.oauthClientId)) { |         if (clientUri === (grant.azp || grant.oauth_client_id || grant.oauthClientId)) { | ||||||
|           return true; |           return true; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user