UNPKG

4.41 kBJavaScriptView Raw
1/****************
2 * IMPORTS
3 */
4
5var util = require('util');
6var OAuth2Strategy = require('passport-oauth2');
7var InternalOAuthError = require('passport-oauth2').InternalOAuthError;
8
9/**
10 * `Strategy` constructor.
11 *
12 * The Microsoft authentication strategy authenticates requests by delegating to
13 * Microsoft using the OAuth 2.0 protocol.
14 *
15 * Applications must supply a `verify` callback which accepts an `accessToken`,
16 * `refreshToken` and service-specific `profile`, and then calls the `done`
17 * callback supplying a `user`, which should be set to `false` if the
18 * credentials are not valid. If an exception occured, `err` should be set.
19 *
20 * Options:
21 * - `clientId` your Microsoft application's client id
22 * - `clientSecret` your Microsoft application's client secret
23 * - `callbackURL` URL to which Microsoft will redirect the user after granting authorization in your Microsoft Application
24 *
25 * Examples:
26 *
27 * var MicrosoftStrategy = require('passport-microsoft').Strategy;
28 *
29 * passport.use(new MicrosoftStrategy({
30 * clientID: '123-456-789',
31 * clientSecret: 'shhh-its-a-secret'
32 * callbackURL: 'https://www.example.net/auth/microsoft/callback'
33 * },
34 * function(accessToken, refreshToken, profile, done) {
35 * User.findOrCreate(..., function (err, user) {
36 * done(err, user);
37 * });
38 * }
39 * ));
40 *
41 * @param {Object} options
42 * @param {Function} verify
43 * @api public
44 */
45
46function MicrosoftStrategy(options, verify) {
47 options = options || {};
48 const tenant = options.tenant || 'common';
49 options.authorizationURL = options.authorizationURL || `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize`;
50 options.tokenURL = options.tokenURL || `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`;
51 options.scopeSeparator = options.scopeSeparator || ' ';
52 options.customHeaders = options.customHeaders || {};
53 options.apiEntryPoint = options.apiEntryPoint || 'https://graph.microsoft.com';
54
55 OAuth2Strategy.call(this, options, verify);
56 this.name = 'microsoft';
57 this._graphApiVersion = options.graphApiVersion || 'v1.0';
58 this._addUPNAsEmail = ('addUPNAsEmail' in options) ? options.addUPNAsEmail : false;
59 this._apiEntryPoint = options.apiEntryPoint;
60}
61
62/**
63 * Inherit from `OAuth2Strategy`.
64 */
65
66util.inherits(MicrosoftStrategy, OAuth2Strategy);
67
68/**
69 * Retrieve user profile from Microsoft Graph.
70 *
71 * This function constructs a normalized profile, with the following properties:
72 *
73 * - `provider` always set to `microsoft`
74 * - `id`
75 * - etc..
76 *
77 * @param {String} accessToken
78 * @param {Function} done
79 * @api protected
80 */
81
82MicrosoftStrategy.prototype.authorizationParams = function(options) {
83 var params = {};
84
85 ['locale', 'display', 'prompt', 'login_hint', 'domain_hint'].forEach(function(name) {
86 if (options[name]) {
87 params[name] = options[name];
88 }
89 });
90
91 return params;
92};
93
94MicrosoftStrategy.prototype.userProfile = function (accessToken, done) {
95 var strategy = this;
96 strategy._oauth2.useAuthorizationHeaderforGET(true);
97 strategy._oauth2.get(
98 `${strategy._apiEntryPoint}/${strategy._graphApiVersion}/me/`,
99 accessToken,
100 // eslint-disable-next-line no-unused-vars
101 function (err, body, res) {
102
103 if (err) {
104 return done(new InternalOAuthError('failed to fetch user profile', err));
105 }
106 try {
107 var json = JSON.parse(body);
108
109 var profile = {
110 provider: 'microsoft',
111 name: {}
112 };
113 profile.id = json.id;
114 profile.displayName = json.displayName;
115 profile.name.familyName = json.surname;
116 profile.name.givenName = json.givenName;
117 profile.userPrincipalName = json.userPrincipalName;
118 profile.emails = [];
119 var isNotEmpty = str => str && typeof str === 'string' && str.trim().length;
120 if (isNotEmpty(json.mail)) {
121 profile.emails.push({ type: 'work', value: json.mail });
122 }
123
124 if (strategy._addUPNAsEmail && isNotEmpty(json.userPrincipalName)) {
125 profile.emails.push({ type: 'work', value: json.userPrincipalName});
126 }
127
128 profile._raw = body;
129 profile._json = json;
130
131 done(null, profile);
132 }
133 catch (e) {
134 done(e);
135 }
136 }
137 );
138};
139
140/**
141 * Expose `Strategy`.
142 */
143
144module.exports = MicrosoftStrategy;
\No newline at end of file