| 
									
										
										
										
											2017-07-24 17:10:41 -06:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var PromiseA = require('bluebird'); | 
					
						
							|  |  |  | var OpErr = PromiseA.OperationalError; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-26 15:51:51 -06:00
										 |  |  | function makeB64UrlSafe(b64) { | 
					
						
							|  |  |  |   return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=*$/, ''); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-12 22:31:11 +00:00
										 |  |  | function checkIssuerToken(req, expectedSub) { | 
					
						
							| 
									
										
										
										
											2017-07-24 17:10:41 -06:00
										 |  |  |   if (!req.oauth3 || !req.oauth3.verifyAsync) { | 
					
						
							|  |  |  |     return PromiseA.reject(new OpErr("request requires a token for authorization")); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return req.oauth3.verifyAsync().then(function (token) { | 
					
						
							|  |  |  |     // Now that we've confirmed the token is valid we also need to make sure the issuer, audience,
 | 
					
						
							|  |  |  |     // and authorized party are all us, because no other app should be managing user identity.
 | 
					
						
							|  |  |  |     if (token.iss !== req.experienceId || token.aud !== token.iss || token.azp !== token.iss) { | 
					
						
							|  |  |  |       throw new OpErr("token does not allow access to requested resource"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var sub = token.sub || token.ppid || (token.acx && (token.acx.id || token.acx.appScopedId)); | 
					
						
							|  |  |  |     if (!sub) { | 
					
						
							|  |  |  |       if (!expectedSub || !Array.isArray(token.axs) || !token.axs.length) { | 
					
						
							|  |  |  |         throw new OpErr("no account pairwise identifier"); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var allowed = token.axs.some(function (acc) { | 
					
						
							|  |  |  |         return expectedSub === (acc.id || acc.ppid || acc.appScopedId); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       if (!allowed) { | 
					
						
							|  |  |  |         throw new OpErr("no account pairwise identifier matching '" + expectedSub + "'"); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       sub = expectedSub; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (expectedSub && expectedSub !== sub) { | 
					
						
							|  |  |  |       throw new OpErr("token does not allow access to resources for '"+expectedSub+"'"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return sub; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 16:32:09 -06:00
										 |  |  | async function getPrimarySub(grantStore, secondary) { | 
					
						
							|  |  |  |   var results = await Promise.all([ | 
					
						
							|  |  |  |     grantStore.find({ sub:    secondary }), | 
					
						
							|  |  |  |     grantStore.find({ azpSub: secondary }), | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Extract only the sub field from each row and reduce the duplicates so that each value
 | 
					
						
							|  |  |  |   // can only appear in the final list once.
 | 
					
						
							|  |  |  |   var subList = [].concat.apply([], results).map(grant => grant.sub); | 
					
						
							|  |  |  |   subList = subList.filter((sub, ind, list) => list.indexOf(sub) === ind); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (subList.length > 1) { | 
					
						
							|  |  |  |     // This should not ever happen since there is a check for PPID collisions when saving
 | 
					
						
							|  |  |  |     // grants, but it's probably better to have this check anyway just incase something
 | 
					
						
							|  |  |  |     // happens that isn't currently accounted for.
 | 
					
						
							|  |  |  |     console.error('acounts ' + JSON.stringify(subList) + ' are all associated with "'+secondary+'"'); | 
					
						
							|  |  |  |     throw new Error('PPID collision'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return subList[0]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-12 22:31:11 +00:00
										 |  |  | module.exports.checkIssuerToken = checkIssuerToken; | 
					
						
							| 
									
										
										
										
											2017-11-03 16:32:09 -06:00
										 |  |  | module.exports.getPrimarySub = getPrimarySub; | 
					
						
							| 
									
										
										
										
											2017-07-26 15:51:51 -06:00
										 |  |  | module.exports.makeB64UrlSafe = makeB64UrlSafe; |