├── .babelrc
├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── lib
└── msal-b2c-react.js
├── package-lock.json
├── package.json
└── src
└── msal-b2c-react.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "react-app"]
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.tabSize": 4
3 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 James Randall
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # README
2 |
3 | Azure AD B2C is a identity provider covering social and enterprise logins.
4 |
5 | The Microsoft Authentication library (MSAL) is JavaScript library to authenticate enterprise users using Microsoft Azure Active Directory (AAD), Microsoft account users (MSA), users using social identity providers like Facebook, Google, LinkedIn etc. and get access to Microsoft Cloud or Microsoft Graph.
6 |
7 | This module is React wrapper over MSAL for Azure AD B2C. It fully supports active SSO sessions.
8 |
9 | ## Installation
10 |
11 | If you are using npm:
12 |
13 | npm install @kdpw/msal-b2c-react --save
14 |
15 | Or if you are using yarn:
16 |
17 | yarn add @kdpw/msal-b2c-react
18 |
19 | ## Initializing the Library
20 |
21 | You'll first need to load the module and pass some configuration to the library. Normally this would go in your index.js file:
22 |
23 | import authentication from '@kdpw/msal-b2c-react';
24 |
25 | authentication.initialize({
26 | // you can user your b2clogin.com domain here, setting is optional, will default to this
27 | instance: 'https://login.microsoftonline.com/tfp/',
28 | // your B2C tenant, you can also user tenants GUID here
29 | tenant: 'myb2ctenant.onmicrosoft.com',
30 | // the policy to use to sign in, can also be a sign up or sign in policy
31 | signInPolicy: 'mysigninpolicy',
32 | // the policy to use for password reset
33 | resetPolicy: 'mypasswordresetpolicy',
34 | // the the B2C application you want to authenticate with (that's just a random GUID - get yours from the portal)
35 | applicationId: '75ee2b43-ad2c-4366-9b8f-84b7d19d776e',
36 | // where MSAL will store state - localStorage or sessionStorage
37 | cacheLocation: 'sessionStorage',
38 | // the scopes you want included in the access token
39 | scopes: ['https://myb2ctenant.onmicrosoft.com/management/admin'],
40 | // optional, the redirect URI - if not specified MSAL will pick up the location from window.href
41 | redirectUri: 'http://localhost:3000',
42 | // optional, the URI to redirect to after logout
43 | postLogoutRedirectUri: 'http://myapp.com',
44 | // optional, default to true, set to false if you change instance
45 | validateAuthority: false,
46 | // optional, default to false, set to true if you only want to acquire token silently and avoid redirections to login page
47 | silentLoginOnly: false
48 | });
49 |
50 | ## Authenticating When The App Starts
51 |
52 | If you want to set things up so that a user is authenticated as soon as they hit your app (for example if you've got a link to an app from a landing page) then, in index.js, wrap the lines of code that launch the React app with the _authentication.run_ function:
53 |
54 | authentication.run(() => {
55 | ReactDOM.render(, document.getElementById('root'));
56 | registerServiceWorker();
57 | });
58 |
59 | ## Triggering Authentication Based on Components Mounting (and routing)
60 |
61 | If you want to set things up so that a user is authenticated as they visit a part of the application that requires authentication then the appropriate components can be wrapped inside higher order components that will handle the authentication process. This is done using the _authentication.required_ function, normally in conjunction with a router. The example below shows this using the popular react-router:
62 |
63 | import React, { Component } from 'react';
64 | import authentication from '@kdpw/msal-b2c-react'
65 | import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
66 | import HomePage from './Homepage'
67 | import MembersArea from './MembersArea'
68 |
69 | class App extends Component {
70 | render() {
71 | return (
72 |
73 |
74 |
75 |
76 |
77 |
78 | );
79 | }
80 | }
81 |
82 | ## Getting the Id Token
83 |
84 | Simply call the method _getIdToken_:
85 |
86 | import authentication from '@kdpw/msal-b2c-react'
87 |
88 | // ...
89 |
90 | const id_token = authentication.getIdToken();
91 |
92 | ## Getting the Access Token
93 |
94 | Simply call the method _getAccessToken_:
95 |
96 | import authentication from '@kdpw/msal-b2c-react'
97 |
98 | // ...
99 |
100 | const access_token = authentication.getAccessToken();
101 |
102 | ## Getting the User Name
103 |
104 | Simply call the method _getUserName_:
105 |
106 | import authentication from '@kdpw/msal-b2c-react'
107 |
108 | // ...
109 |
110 | const userName = authentication.getUserName();
111 |
112 | ## Signing Out
113 |
114 | To sign out:
115 |
116 | import authentication from '@kdpw/msal-b2c-react'
117 |
118 | // ...
119 |
120 | authentication.signOut();
121 |
122 | ## Thanks
123 |
124 | To build this I made fork of [react-azure-adb2c](https://github.com/JamesRandall/react-azure-adb2c) module. Thanks!
125 |
--------------------------------------------------------------------------------
/lib/msal-b2c-react.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _msal = require('msal');
10 |
11 | var Msal = _interopRequireWildcard(_msal);
12 |
13 | var _react = require('react');
14 |
15 | var _react2 = _interopRequireDefault(_react);
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
20 |
21 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22 |
23 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
24 |
25 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // note on window.msal usage. There is little point holding the object constructed by new Msal.UserAgentApplication
26 | // as the constructor for this class will make callbacks to the acquireToken function and these occur before
27 | // any local assignment can take place. Not nice but its how it works.
28 |
29 |
30 | var logger = new Msal.Logger(loggerCallback, {
31 | level: Msal.LogLevel.Warning
32 | });
33 | var state = {
34 | noScopes: false,
35 | launchApp: null,
36 | idToken: null,
37 | accessToken: null,
38 | userName: ""
39 | };
40 | var appConfig = {
41 | // optional, will default to 'https://login.microsoftonline.com/tfp/'
42 | instance: null,
43 | // your B2C tenant
44 | tenant: null,
45 | // the policy to use to sign in, can also be a sign up or sign in policy
46 | signInPolicy: null,
47 | // the policy to use for password reset
48 | resetPolicy: null,
49 | // the the B2C application you want to authenticate with
50 | applicationId: null,
51 | // where MSAL will store state - localStorage or sessionStorage
52 | cacheLocation: null,
53 | // optional, the scopes you want included in the access token
54 | scopes: [],
55 | // optional, the redirect URI - if not specified MSAL will pick up the location from window.href
56 | redirectUri: null,
57 | // optional, the URI to redirect to after logout
58 | postLogoutRedirectUri: null,
59 | // optional, default to true, set to false if you change instance
60 | validateAuthority: null,
61 | // optional, default to false, set to true if you want to acquire token silently and avoid redirections to login page
62 | silentLoginOnly: false
63 | };
64 |
65 | function loggerCallback(logLevel, message, piiLoggingEnabled) {
66 | console.log(message);
67 | }
68 |
69 | function authCallback(errorDesc, token, error, tokenType) {
70 | if (errorDesc && errorDesc.indexOf('AADB2C90118') > -1) {
71 | redirect();
72 | } else if (errorDesc) {
73 | console.log(error + ':' + errorDesc);
74 | } else {}
75 | }
76 |
77 | function redirect() {
78 | var localMsalApp = window.msal;
79 | var instance = appConfig.instance ? appConfig.instance : 'https://login.microsoftonline.com/tfp/';
80 | var authority = '' + instance + appConfig.tenant + '/' + appConfig.resetPolicy;
81 | localMsalApp.authority = authority;
82 | loginAndAcquireToken();
83 | }
84 |
85 | function loginAndAcquireToken(successCallback) {
86 | var localMsalApp = window.msal;
87 | var user = localMsalApp.getUser(appConfig.scopes);
88 |
89 | if (!user) {
90 |
91 | // user is not logged in
92 | if (state.noScopes) {
93 | // no need of access token
94 | if (appConfig.silentLoginOnly) {
95 | // on silent mode we call error app
96 | if (state.errorApp) state.errorApp();
97 | } else
98 | // just redirect to login page
99 | localMsalApp.loginRedirect(appConfig.scopes);
100 | } else {
101 | // try to get token from SSO session
102 | localMsalApp.acquireTokenSilent(appConfig.scopes, null, null, "&login_hint&domain_hint=organizations").then(function (accessToken) {
103 | state.accessToken = accessToken;
104 | user = localMsalApp.getUser(appConfig.scopes);
105 | state.idToken = user.idToken;
106 | state.userName = user.name;
107 | if (state.launchApp) {
108 | state.launchApp();
109 | }
110 | if (successCallback) {
111 | successCallback();
112 | }
113 | }, function (error) {
114 | if (error) {
115 | if (appConfig.silentLoginOnly) state.errorApp();else localMsalApp.loginRedirect(appConfig.scopes);
116 | }
117 | });
118 | }
119 | } else {
120 |
121 | // the user is already logged in
122 | state.idToken = user.idToken;
123 | state.userName = user.name;
124 | if (state.noScopes) {
125 | // no need of access token, just launch the app
126 | if (state.launchApp) {
127 | state.launchApp();
128 | }
129 | if (successCallback) {
130 | successCallback();
131 | }
132 | } else {
133 | // get access token
134 | localMsalApp.acquireTokenSilent(appConfig.scopes).then(function (accessToken) {
135 | state.accessToken = accessToken;
136 | if (state.launchApp) {
137 | state.launchApp();
138 | }
139 | if (successCallback) {
140 | successCallback();
141 | }
142 | }, function (error) {
143 | if (error) {
144 | localMsalApp.acquireTokenRedirect(appConfig.scopes);
145 | }
146 | });
147 | }
148 | }
149 | }
150 |
151 | var authentication = {
152 | initialize: function initialize(config) {
153 | appConfig = config;
154 | var instance = config.instance ? config.instance : 'https://login.microsoftonline.com/tfp/';
155 | var authority = '' + instance + config.tenant + '/' + config.signInPolicy;
156 | var validateAuthority = config.validateAuthority != null ? config.validateAuthority : true;
157 | var scopes = config.scopes;
158 | if (!scopes || scopes.length === 0) {
159 | console.log('To obtain access tokens you must specify one or more scopes. See https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-access-tokens');
160 | state.noScopes = true;
161 | }
162 | state.scopes = scopes;
163 |
164 | new Msal.UserAgentApplication(config.applicationId, authority, authCallback, {
165 | logger: logger,
166 | cacheLocation: config.cacheLocation,
167 | postLogoutRedirectUri: config.postLogoutRedirectUri,
168 | redirectUri: config.redirectUri,
169 | validateAuthority: validateAuthority
170 | });
171 | },
172 | run: function run(launchApp, errorApp) {
173 | state.launchApp = launchApp;
174 | if (errorApp) state.errorApp = errorApp;
175 | if (!window.msal.isCallback(window.location.hash) && window.parent === window && !window.opener) {
176 | loginAndAcquireToken();
177 | }
178 | },
179 | required: function required(WrappedComponent, renderLoading) {
180 | return function (_React$Component) {
181 | _inherits(_class, _React$Component);
182 |
183 | function _class(props) {
184 | _classCallCheck(this, _class);
185 |
186 | var _this = _possibleConstructorReturn(this, (_class.__proto__ || Object.getPrototypeOf(_class)).call(this, props));
187 |
188 | _this.state = {
189 | signedIn: false,
190 | error: null
191 | };
192 | return _this;
193 | }
194 |
195 | _createClass(_class, [{
196 | key: 'componentWillMount',
197 | value: function componentWillMount() {
198 | var _this2 = this;
199 |
200 | loginAndAcquireToken(function () {
201 | _this2.setState(Object.assign({}, _this2.state, {
202 | signedIn: true
203 | }));
204 | });
205 | }
206 | }, {
207 | key: 'render',
208 | value: function render() {
209 | if (this.state.signedIn) {
210 | return _react2.default.createElement(WrappedComponent, this.props);
211 | };
212 | return typeof renderLoading === 'function' ? renderLoading() : null;
213 | }
214 | }]);
215 |
216 | return _class;
217 | }(_react2.default.Component);
218 | },
219 | signOut: function signOut() {
220 | window.msal.logout();
221 | },
222 | getIdToken: function getIdToken() {
223 | return state.idToken;
224 | },
225 | getAccessToken: function getAccessToken() {
226 | return state.accessToken;
227 | },
228 | getUserName: function getUserName() {
229 | return state.userName;
230 | }
231 | };
232 |
233 | exports.default = authentication;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@kdpw/msal-b2c-react",
3 | "version": "0.0.3",
4 | "description": "React wrapper over MS Authentication library for Azure AD B2C",
5 | "main": "lib/msal-b2c-react.js",
6 | "scripts": {
7 | "compile": "cross-env NODE_ENV=production babel src --out-dir lib",
8 | "prepublish": "npm run compile"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/leszekczajka/msal-b2c-react.git"
13 | },
14 | "keywords": [
15 | "react",
16 | "js",
17 | "AAD",
18 | "B2C",
19 | "oauth",
20 | "azure",
21 | "msal"
22 | ],
23 | "author": "James Randall",
24 | "contributors": [
25 | "Leszek Czajka "
26 | ],
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/leszekczajka/msal-b2c-react/issues"
30 | },
31 | "homepage": "https://github.com/leszekczajka/msal-b2c-react#readme",
32 | "dependencies": {
33 | "msal": "^0.2.3"
34 | },
35 | "peerDependencies": {
36 | "react": "^15.0.0 || ^16.0.0"
37 | },
38 | "devDependencies": {
39 | "babel-cli": "^6.26.0",
40 | "babel-core": "6.24.1",
41 | "babel-eslint": "^8.0.3",
42 | "babel-jest": "20.0.3",
43 | "babel-loader": "7.0.0",
44 | "babel-plugin-import": "^1.2.1",
45 | "babel-polyfill": "^6.23.0",
46 | "babel-preset-env": "^1.6.1",
47 | "babel-runtime": "6.23.0",
48 | "babel-preset-react-app": "^3.0.0",
49 | "cross-env": "^5.1.4",
50 | "eslint": "^4.12.1",
51 | "eslint-config-airbnb": "^16.1.0",
52 | "eslint-config-defaults": "^9.0.0",
53 | "eslint-plugin-import": "^2.8.0",
54 | "eslint-plugin-jsx-a11y": "^6.0.2",
55 | "eslint-plugin-react": "^7.5.1"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/msal-b2c-react.js:
--------------------------------------------------------------------------------
1 | // note on window.msal usage. There is little point holding the object constructed by new Msal.UserAgentApplication
2 | // as the constructor for this class will make callbacks to the acquireToken function and these occur before
3 | // any local assignment can take place. Not nice but its how it works.
4 | import * as Msal from 'msal';
5 | import React from 'react';
6 |
7 | const logger = new Msal.Logger(loggerCallback, {
8 | level: Msal.LogLevel.Warning
9 | });
10 | const state = {
11 | noScopes: false,
12 | launchApp: null,
13 | idToken: null,
14 | accessToken: null,
15 | userName: ""
16 | }
17 | var appConfig = {
18 | // optional, will default to 'https://login.microsoftonline.com/tfp/'
19 | instance: null,
20 | // your B2C tenant
21 | tenant: null,
22 | // the policy to use to sign in, can also be a sign up or sign in policy
23 | signInPolicy: null,
24 | // the policy to use for password reset
25 | resetPolicy: null,
26 | // the the B2C application you want to authenticate with
27 | applicationId: null,
28 | // where MSAL will store state - localStorage or sessionStorage
29 | cacheLocation: null,
30 | // optional, the scopes you want included in the access token
31 | scopes: [],
32 | // optional, the redirect URI - if not specified MSAL will pick up the location from window.href
33 | redirectUri: null,
34 | // optional, the URI to redirect to after logout
35 | postLogoutRedirectUri: null,
36 | // optional, default to true, set to false if you change instance
37 | validateAuthority: null,
38 | // optional, default to false, set to true if you want to acquire token silently and avoid redirections to login page
39 | silentLoginOnly: false
40 | };
41 |
42 | function loggerCallback(logLevel, message, piiLoggingEnabled) {
43 | console.log(message);
44 | }
45 |
46 | function authCallback(errorDesc, token, error, tokenType) {
47 | if (errorDesc && errorDesc.indexOf('AADB2C90118') > -1) {
48 | redirect();
49 | } else if (errorDesc) {
50 | console.log(error + ':' + errorDesc);
51 | } else {}
52 | }
53 |
54 | function redirect() {
55 | const localMsalApp = window.msal;
56 | const instance = appConfig.instance ? appConfig.instance : 'https://login.microsoftonline.com/tfp/';
57 | const authority = `${instance}${appConfig.tenant}/${appConfig.resetPolicy}`;
58 | localMsalApp.authority = authority;
59 | loginAndAcquireToken();
60 | }
61 |
62 | function loginAndAcquireToken(successCallback) {
63 | const localMsalApp = window.msal;
64 | let user = localMsalApp.getUser(appConfig.scopes);
65 |
66 | if (!user) {
67 |
68 | // user is not logged in
69 | if (state.noScopes) {
70 | // no need of access token
71 | if (appConfig.silentLoginOnly) {
72 | // on silent mode we call error app
73 | if (state.errorApp)
74 | state.errorApp();
75 | } else
76 | // just redirect to login page
77 | localMsalApp.loginRedirect(appConfig.scopes);
78 | } else {
79 | // try to get token from SSO session
80 | localMsalApp.acquireTokenSilent(appConfig.scopes, null, null, "&login_hint&domain_hint=organizations").then(accessToken => {
81 | state.accessToken = accessToken;
82 | user = localMsalApp.getUser(appConfig.scopes);
83 | state.idToken = user.idToken;
84 | state.userName = user.name;
85 | if (state.launchApp) {
86 | state.launchApp();
87 | }
88 | if (successCallback) {
89 | successCallback();
90 | }
91 | }, error => {
92 | if (error) {
93 | if (appConfig.silentLoginOnly)
94 | state.errorApp();
95 | else
96 | localMsalApp.loginRedirect(appConfig.scopes);
97 | }
98 | });
99 | }
100 |
101 | } else {
102 |
103 | // the user is already logged in
104 | state.idToken = user.idToken;
105 | state.userName = user.name;
106 | if (state.noScopes) {
107 | // no need of access token, just launch the app
108 | if (state.launchApp) {
109 | state.launchApp();
110 | }
111 | if (successCallback) {
112 | successCallback();
113 | }
114 | } else {
115 | // get access token
116 | localMsalApp.acquireTokenSilent(appConfig.scopes).then(accessToken => {
117 | state.accessToken = accessToken;
118 | if (state.launchApp) {
119 | state.launchApp();
120 | }
121 | if (successCallback) {
122 | successCallback();
123 | }
124 | }, error => {
125 | if (error) {
126 | localMsalApp.acquireTokenRedirect(appConfig.scopes);
127 | }
128 | });
129 | }
130 |
131 | }
132 |
133 | }
134 |
135 | const authentication = {
136 | initialize: (config) => {
137 | appConfig = config;
138 | const instance = config.instance ? config.instance : 'https://login.microsoftonline.com/tfp/';
139 | const authority = `${instance}${config.tenant}/${config.signInPolicy}`;
140 | const validateAuthority = (config.validateAuthority != null) ? config.validateAuthority : true;
141 | let scopes = config.scopes;
142 | if (!scopes || scopes.length === 0) {
143 | console.log('To obtain access tokens you must specify one or more scopes. See https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-access-tokens');
144 | state.noScopes = true;
145 | }
146 | state.scopes = scopes;
147 |
148 | new Msal.UserAgentApplication(
149 | config.applicationId,
150 | authority,
151 | authCallback, {
152 | logger: logger,
153 | cacheLocation: config.cacheLocation,
154 | postLogoutRedirectUri: config.postLogoutRedirectUri,
155 | redirectUri: config.redirectUri,
156 | validateAuthority: validateAuthority
157 | }
158 | );
159 | },
160 | run: (launchApp, errorApp) => {
161 | state.launchApp = launchApp
162 | if (errorApp)
163 | state.errorApp = errorApp;
164 | if (!window.msal.isCallback(window.location.hash) && window.parent === window && !window.opener) {
165 | loginAndAcquireToken();
166 | }
167 | },
168 | required: (WrappedComponent, renderLoading) => {
169 | return class extends React.Component {
170 | constructor(props) {
171 | super(props);
172 | this.state = {
173 | signedIn: false,
174 | error: null,
175 | };
176 | }
177 |
178 | componentWillMount() {
179 | loginAndAcquireToken(() => {
180 | this.setState({
181 | ...this.state,
182 | signedIn: true
183 | });
184 | });
185 | };
186 |
187 | render() {
188 | if (this.state.signedIn) {
189 | return ( < WrappedComponent {
190 | ...this.props
191 | }
192 | />);
193 | };
194 | return typeof renderLoading === 'function' ? renderLoading() : null;
195 | };
196 | };
197 | },
198 | signOut: () => {
199 | window.msal.logout()
200 | },
201 | getIdToken: () => {
202 | return state.idToken;
203 | },
204 | getAccessToken: () => {
205 | return state.accessToken;
206 | },
207 | getUserName: () => {
208 | return state.userName;
209 | }
210 | }
211 |
212 | export default authentication;
--------------------------------------------------------------------------------