Skip to content

Commit 6c358d7

Browse files
authored
Merge pull request #1 from Azure-Samples/moving-from-vsts
Moving sync week project from VSTS to GH.
2 parents 46c8184 + ace1a4e commit 6c358d7

25 files changed

+13891
-109
lines changed

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# http://editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
indent_style = space
8+
indent_size = 2
9+
end_of_line = lf
10+
insert_final_newline = true
11+
trim_trailing_whitespace = true
12+
13+
[*.md]
14+
insert_final_newline = false
15+
trim_trailing_whitespace = false

.gitignore

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,26 @@
1-
# Logs
2-
logs
3-
*.log
4-
npm-debug.log*
5-
yarn-debug.log*
6-
yarn-error.log*
7-
8-
# Runtime data
9-
pids
10-
*.pid
11-
*.seed
12-
*.pid.lock
13-
14-
# Directory for instrumented libs generated by jscoverage/JSCover
15-
lib-cov
16-
17-
# Coverage directory used by tools like istanbul
18-
coverage
19-
20-
# nyc test coverage
21-
.nyc_output
22-
23-
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24-
.grunt
1+
# See https://help.github.com/ignore-files/ for more about ignoring files.
252

26-
# Bower dependency directory (https://bower.io/)
27-
bower_components
3+
# dependencies
4+
**/node_modules
285

29-
# node-waf configuration
30-
.lock-wscript
6+
# testing
7+
/coverage
318

32-
# Compiled binary addons (http://nodejs.org/api/addons.html)
33-
build/Release
9+
# production
10+
/dist
3411

35-
# Dependency directories
36-
node_modules/
37-
jspm_packages/
12+
# misc
13+
.DS_Store
14+
.env.local
15+
.env.development.local
16+
.env.test.local
17+
.env.production.local
3818

39-
# Typescript v1 declaration files
40-
typings/
41-
42-
# Optional npm cache directory
43-
.npm
44-
45-
# Optional eslint cache
46-
.eslintcache
47-
48-
# Optional REPL history
49-
.node_repl_history
50-
51-
# Output of 'npm pack'
52-
*.tgz
53-
54-
# Yarn Integrity file
55-
.yarn-integrity
19+
npm-debug.log*
20+
yarn-debug.log*
21+
yarn-error.log*
5622

57-
# dotenv environment variables file
58-
.env
23+
.vscode
5924

25+
#build
26+
/build

README.md

Lines changed: 97 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,97 @@
1-
# Project Name
2-
3-
(short, 1-3 sentenced, description of the project)
4-
5-
## Features
6-
7-
This project framework provides the following features:
8-
9-
* Feature 1
10-
* Feature 2
11-
* ...
12-
13-
## Getting Started
14-
15-
### Prerequisites
16-
17-
(ideally very short, if any)
18-
19-
- OS
20-
- Library version
21-
- ...
22-
23-
### Installation
24-
25-
(ideally very short)
26-
27-
- npm install [package name]
28-
- mvn install
29-
- ...
30-
31-
### Quickstart
32-
(Add steps to get up and running quickly)
33-
34-
1. git clone [repository clone url]
35-
2. cd [respository name]
36-
3. ...
37-
38-
39-
## Demo
40-
41-
A demo app is included to show how to use the project.
42-
43-
To run the demo, follow these steps:
44-
45-
(Add steps to start up the demo)
46-
47-
1.
48-
2.
49-
3.
50-
51-
## Resources
52-
53-
(Any additional resources or related projects)
54-
55-
- Link to supporting information
56-
- Link to similar sample
57-
- ...
1+
## React AAD MSAL
2+
3+
![build status](https://reactaad.visualstudio.com/_apis/public/build/definitions/1c71aebc-1683-48cd-9ab2-8663e6a4ec55/5/badge)
4+
5+
### Overview
6+
React AAD MSAL is a library to easily integrate the Microsoft Authentication Library with Azure Active Directory in your React app quickly and reliably. The library focuses on flexibility, allowing you to define how you want to interact with logins and logouts.
7+
### Setup
8+
In the render module of your component, make sure to create an AzureAD component with the arguments you need. This uses the functions that you will define. Once the user is successfully authenticated, the component will render the OnAuthenticationComponent given. This is where you should put the secure, user-specific parts of your app. `loginCallback` and `printUserInfo` can be any user defined functions.
9+
10+
11+
Find the assignment for ClientID and replace the value with the Application ID for your application from the azure portal. The authority is the sign-in/signup policy for your application. Graph scopes is a list of scope URLs that you want to grant access to. You can find more information on the [active directory MSAL single page app azure sample](https://github.com/Azure-Samples/active-directory-b2c-javascript-msal-singlepageapp).
12+
```javascript
13+
// ...
14+
15+
return (
16+
<AzureAD
17+
clientID={'<Application ID for your application>'}
18+
graphScopes={['https://<your-tenant-name>.onmicrosoft.com/hello/demo.read']}
19+
unauthenticatedFunction={this.loginCallback}
20+
authenticatedFunction={this.logoutCallback}
21+
userInfoCallback={this.printUserInfo}
22+
authority={'https://login.microsoftonline.com/tfp/<your-tenant-name>.onmicrosoft.com/<your-sign-in-sign-up-policy>'}
23+
type={LoginType.Popup}>
24+
<OnAuthenticationComponent />
25+
</AzureAD>
26+
);
27+
```
28+
### Login
29+
To login, first create a callback function for the AzureAD component to consume. This function will be called when the component loads, and it will pass in the function to be called when the user wants to login. In this case, we create a button that will log the user in.
30+
```javascript
31+
import AzureAD from 'AzureAD'
32+
33+
loginCallback = (login) => {
34+
return <button onclick={login}>Login</button>;
35+
};
36+
// ...
37+
```
38+
Once they're logged in, the AzureAD library will call another function given with an `IUserInfo` instance. You can do whatever you want with this, but you should store it. In this example, we just print it out to console.
39+
```javascript
40+
//...
41+
printUserInfo = (userInfo) => {console.log(userInfo)};
42+
//...
43+
```
44+
45+
Once you've set this up, you should be able to set up a button to login that will hit an AAD instance. To set up your instance, check out the documentation on [Azure Active Directory](https://docs.microsoft.com/en-us/azure/active-directory-b2c/) and on how to connect an [Identity Provider](https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-setup-msa-app) for that AAD instance.
46+
47+
### Logout
48+
49+
Logging out is just as easy.
50+
```javascript
51+
logoutCallback = (logout) => {
52+
return <button onclick={logout}>Logout</button>;
53+
};
54+
```
55+
You can, of course, include a component in either of these functions. This allows you to gate which view of your application users get, based on whether or not they are authenticated.
56+
57+
### Samples
58+
59+
If you want to run examples of this library out of the box, feel free to go to [the samples repo](https://reactaad.visualstudio.com/react-aad-msal/). There you'll find a couple implementations that leverage the library, as well as a tutorial of how to set up Azure Active Directory with an Identity Provider.
60+
61+
### Integrating with a Redux Store
62+
63+
The Azure AD component optionally accepts a ```reduxStore``` prop. On successful login, Azure AD will dispatch an action of type ```AAD_LOGIN_SUCCESS``` to the provided store, containing the token and user information returned from Active Directory. It does the same for logout events, but the action will not contain a payload.
64+
65+
Import your store into the file rendering the AzureAD component and pass it in:
66+
67+
```javascript
68+
<AzureAD
69+
reduxStore={store}
70+
clientID={'<Application ID for your application>'}
71+
graphScopes={['https://<your-tenant-name>.onmicrosoft.com/hello/demo.read']}
72+
unauthenticatedFunction={this.loginCallback}
73+
authenticatedFunction={this.logoutCallback}
74+
userInfoCallback={this.printUserInfo}
75+
authority={'https://login.microsoftonline.com/tfp/<your-tenant-name>.onmicrosoft.com/<your-sign-in-sign-up-policy>'}
76+
type={LoginType.Popup}
77+
/>
78+
```
79+
80+
Add a case to handle ```AAD_LOGIN_SUCCESS``` and ```AAD_LOGOUT_SUCCESS``` actions in a reducer file:
81+
82+
```javascript
83+
const initialState = {
84+
aadResponse: null,
85+
};
86+
87+
const sampleReducer = (state = initialState, action) => {
88+
switch (action.type) {
89+
case 'AAD_LOGIN_SUCCESS':
90+
return { ...state, aadResponse: action.payload };
91+
case 'AAD_LOGOUT_SUCCESS':
92+
return { ...state, aadResponse: null};
93+
default:
94+
return state;
95+
}
96+
};
97+
```

config/env.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
'use strict';
2+
3+
const fs = require('fs');
4+
const path = require('path');
5+
const paths = require('./paths');
6+
7+
// Make sure that including paths.js after env.js will read .env variables.
8+
delete require.cache[require.resolve('./paths')];
9+
10+
const NODE_ENV = process.env.NODE_ENV;
11+
if (!NODE_ENV) {
12+
throw new Error(
13+
'The NODE_ENV environment variable is required but was not specified.'
14+
);
15+
}
16+
17+
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
18+
var dotenvFiles = [
19+
`${paths.dotenv}.${NODE_ENV}.local`,
20+
`${paths.dotenv}.${NODE_ENV}`,
21+
// Don't include `.env.local` for `test` environment
22+
// since normally you expect tests to produce the same
23+
// results for everyone
24+
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
25+
paths.dotenv,
26+
].filter(Boolean);
27+
28+
// Load environment variables from .env* files. Suppress warnings using silent
29+
// if this file is missing. dotenv will never modify any environment variables
30+
// that have already been set. Variable expansion is supported in .env files.
31+
// https://github.com/motdotla/dotenv
32+
// https://github.com/motdotla/dotenv-expand
33+
dotenvFiles.forEach(dotenvFile => {
34+
if (fs.existsSync(dotenvFile)) {
35+
require('dotenv-expand')(
36+
require('dotenv').config({
37+
path: dotenvFile,
38+
})
39+
);
40+
}
41+
});
42+
43+
// We support resolving modules according to `NODE_PATH`.
44+
// This lets you use absolute paths in imports inside large monorepos:
45+
// https://github.com/facebookincubator/create-react-app/issues/253.
46+
// It works similar to `NODE_PATH` in Node itself:
47+
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
48+
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
49+
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
50+
// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
51+
// We also resolve them to make sure all tools using them work consistently.
52+
const appDirectory = fs.realpathSync(process.cwd());
53+
process.env.NODE_PATH = (process.env.NODE_PATH || '')
54+
.split(path.delimiter)
55+
.filter(folder => folder && !path.isAbsolute(folder))
56+
.map(folder => path.resolve(appDirectory, folder))
57+
.join(path.delimiter);
58+
59+
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
60+
// injected into the application via DefinePlugin in Webpack configuration.
61+
const REACT_APP = /^REACT_APP_/i;
62+
63+
function getClientEnvironment(publicUrl) {
64+
const raw = Object.keys(process.env)
65+
.filter(key => REACT_APP.test(key))
66+
.reduce(
67+
(env, key) => {
68+
env[key] = process.env[key];
69+
return env;
70+
},
71+
{
72+
// Useful for determining whether we’re running in production mode.
73+
// Most importantly, it switches React into the correct mode.
74+
NODE_ENV: process.env.NODE_ENV || 'development',
75+
// Useful for resolving the correct path to static assets in `public`.
76+
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
77+
// This should only be used as an escape hatch. Normally you would put
78+
// images into the `src` and `import` them in code to get their paths.
79+
PUBLIC_URL: publicUrl,
80+
}
81+
);
82+
// Stringify all values so we can feed into Webpack DefinePlugin
83+
const stringified = {
84+
'process.env': Object.keys(raw).reduce(
85+
(env, key) => {
86+
env[key] = JSON.stringify(raw[key]);
87+
return env;
88+
},
89+
{}
90+
),
91+
};
92+
93+
return { raw, stringified };
94+
}
95+
96+
module.exports = getClientEnvironment;

config/jest/cssTransform.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
3+
// This is a custom Jest transformer turning style imports into empty objects.
4+
// http://facebook.github.io/jest/docs/en/webpack.html
5+
6+
module.exports = {
7+
process() {
8+
return 'module.exports = {};';
9+
},
10+
getCacheKey() {
11+
// The output is always the same.
12+
return 'cssTransform';
13+
},
14+
};

config/jest/fileTransform.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
5+
// This is a custom Jest transformer turning file imports into filenames.
6+
// http://facebook.github.io/jest/docs/en/webpack.html
7+
8+
module.exports = {
9+
process(src, filename) {
10+
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
11+
},
12+
};

config/jest/typescriptTransform.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2004-present Facebook. All Rights Reserved.
2+
3+
'use strict';
4+
5+
const tsJestPreprocessor = require('ts-jest/preprocessor');
6+
7+
module.exports = tsJestPreprocessor;

0 commit comments

Comments
 (0)