OpenIdConnect.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* Copyright 2015-2016 PayPal, Inc. */
  2. "use strict";
  3. var configuration = require('../configure');
  4. var client = require('../client');
  5. var utils = require('../utils');
  6. var querystring = require('querystring');
  7. /**
  8. * Sets up request body for open id connect module requests
  9. * @param {String} path url endpoint
  10. * @param {Object} data Payload for HTTP Request
  11. * @param {Object|Function} config Configuration parameters such as authorization code or refresh token
  12. * @param {Function} cb
  13. */
  14. function openIdConnectRequest(path, data, config, cb) {
  15. var http_options = {
  16. schema: config.openid_connect_schema || configuration.default_options.openid_connect_schema,
  17. host: utils.getDefaultApiEndpoint(config.mode) || config.openid_connect_host,
  18. port: config.openid_connect_port || configuration.default_options.openid_connect_port,
  19. headers: {
  20. 'Accept': 'application/json',
  21. 'Content-Type': 'application/x-www-form-urlencoded'
  22. }
  23. };
  24. //Populate Basic Auth header only for endpoints that need it such as tokeninfo
  25. if (data.client_id && data.client_secret) {
  26. http_options.headers.Authorization = 'Basic ' + new Buffer(data.client_id + ':' + data.client_secret).toString('base64');
  27. }
  28. client.invoke('POST', path, querystring.stringify(data), http_options, cb);
  29. }
  30. /**
  31. * @param {Object} config Configurations for settings and Auth
  32. * @return {String} client id
  33. */
  34. function getClientId(config) {
  35. return config.openid_client_id || config.client_id ||
  36. configuration.default_options.openid_client_id || configuration.default_options.client_id;
  37. }
  38. /**
  39. * @param {Object} config Configurations for settings and Auth
  40. * @return {String} client secret
  41. */
  42. function getClientSecret(config) {
  43. return config.openid_client_secret || config.client_secret ||
  44. configuration.default_options.openid_client_secret || configuration.default_options.client_secret;
  45. }
  46. /**
  47. * Configurations for settings and Auth
  48. * @return {String} redirect uri
  49. */
  50. function getRedirectUri(config) {
  51. return config.openid_redirect_uri || configuration.default_options.openid_redirect_uri;
  52. }
  53. /**
  54. * Obtain a user’s consent to make Identity API calls on their behalf by redirecting them
  55. * to authorization endpoint
  56. * @param {Data} data Payload associated with API request
  57. * @param {Object} config Configurations for settings and Auth
  58. * @return {String} authorize url
  59. */
  60. function authorizeUrl(data, config) {
  61. config = config || configuration.default_options;
  62. data = data || {};
  63. //Use mode provided, live or sandbox to construct authorize_url, sandbox is default
  64. var url = 'https://www.' + utils.getDefaultEndpoint(config.mode) + '/signin/authorize' || config.authorize_url;
  65. data = utils.merge({
  66. 'client_id': getClientId(config),
  67. 'scope': 'openid',
  68. 'response_type': 'code',
  69. 'redirect_uri': getRedirectUri(config)
  70. }, data);
  71. return url + '?' + querystring.stringify(data);
  72. }
  73. /**
  74. * Direct user to logout url to end session
  75. * @param {Data} data Payload associated with API request
  76. * @param {Object} config Configurations for settings and Auth
  77. * @return {String} logout url
  78. */
  79. function logoutUrl(data, config) {
  80. config = config || configuration.default_options;
  81. data = data || {};
  82. var url = 'https://www.' + utils.getDefaultEndpoint(config.mode) + '/webapps/auth/protocol/openidconnect/v1/endsession' || config.logout_url;
  83. if (typeof data === 'string') {
  84. data = { 'id_token': data };
  85. }
  86. data = utils.merge({
  87. 'logout': 'true',
  88. 'redirect_uri': getRedirectUri(config)
  89. }, data);
  90. return url + '?' + querystring.stringify(data);
  91. }
  92. /**
  93. * Grant a new access token, using a refresh token
  94. * @param {Object} data Payload associated with API request
  95. * @param {Object|Function} config Configurations for settings and Auth
  96. * @param {Function} cb Callback function
  97. */
  98. function tokenInfoRequest(data, config, cb) {
  99. if (typeof config === 'function') {
  100. cb = config;
  101. config = configuration.default_options;
  102. } else if (!config) {
  103. config = configuration.default_options;
  104. }
  105. data = utils.merge({
  106. 'client_id': getClientId(config),
  107. 'client_secret': getClientSecret(config)
  108. }, data);
  109. openIdConnectRequest('/v1/identity/openidconnect/tokenservice', data, config, cb);
  110. }
  111. /**
  112. * Retrieve user profile attributes
  113. * @param {Object} data Payload associated with API request
  114. * @param {Object|Function} config Configurations for settings and Auth
  115. * @param {Function} cb Callback function
  116. */
  117. function userInfoRequest(data, config, cb) {
  118. if (typeof config === 'function') {
  119. cb = config;
  120. config = configuration.default_options;
  121. } else if (!config) {
  122. config = configuration.default_options;
  123. }
  124. if (typeof data === 'string') {
  125. data = { 'access_token': data };
  126. }
  127. data = utils.merge({
  128. 'schema': 'openid'
  129. }, data);
  130. openIdConnectRequest('/v1/identity/openidconnect/userinfo', data, config, cb);
  131. }
  132. /**
  133. * Use log in with PayPal to avoid storing user data on the system
  134. * @return {Object} openidconnect functions
  135. */
  136. function openIdConnect() {
  137. return {
  138. tokeninfo: {
  139. create: function (data, config, cb) {
  140. if (typeof data === 'string') {
  141. data = { 'code': data };
  142. }
  143. data.grant_type = 'authorization_code';
  144. tokenInfoRequest(data, config, cb);
  145. },
  146. refresh: function (data, config, cb) {
  147. if (typeof data === 'string') {
  148. data = { 'refresh_token': data };
  149. }
  150. data.grant_type = 'refresh_token';
  151. tokenInfoRequest(data, config, cb);
  152. }
  153. },
  154. authorizeUrl: authorizeUrl,
  155. logoutUrl: logoutUrl,
  156. userinfo: {
  157. get: userInfoRequest
  158. },
  159. //entries below are deprecated but provided for compatibility with 0.* versions
  160. authorize_url: authorizeUrl,
  161. logout_url: logoutUrl
  162. };
  163. }
  164. module.exports = openIdConnect;