Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cognito hosted ui #585

Merged
merged 33 commits into from
Apr 13, 2018
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
17f0285
mionr chnage
powerful23 Mar 22, 2018
0205024
Merge remote-tracking branch 'upstream/master' into cognito-hosted-ui
powerful23 Mar 22, 2018
e2c0202
mionr change
powerful23 Mar 23, 2018
b7ee2fe
mionr change
powerful23 Mar 23, 2018
118560c
merge upstream
powerful23 Mar 28, 2018
ebcbb77
mionr change
powerful23 Mar 29, 2018
d7b33bb
mionr change
powerful23 Mar 30, 2018
957d7ea
documentation updated
powerful23 Apr 3, 2018
711bc54
mionr change
powerful23 Apr 3, 2018
9ad6619
Merge remote-tracking branch 'upstream/master' into cognito-hosted-ui
powerful23 Apr 3, 2018
373ddf5
merge from upstream
powerful23 Apr 3, 2018
cf02930
rename withCognito to withHostedCognito
powerful23 Apr 3, 2018
b4bb820
unit tests fix
powerful23 Apr 3, 2018
68d1846
authenticator and auth_configure fix
powerful23 Apr 5, 2018
ac63813
Merge remote-tracking branch 'upstream/master' into cognito-hosted-ui
powerful23 Apr 5, 2018
cde081b
cognito session refresh and unit tests
powerful23 Apr 5, 2018
facffd6
version claim
powerful23 Apr 6, 2018
b2c14d2
unit tests for aws-amplify-react
powerful23 Apr 6, 2018
053a9e5
Merge branch 'master' into cognito-hosted-ui
powerful23 Apr 6, 2018
0908d71
Merge remote-tracking branch 'upstream/master' into cognito-hosted-ui
powerful23 Apr 6, 2018
523f355
documentation updated
powerful23 Apr 6, 2018
5b21c27
Merge branch 'master' into cognito-hosted-ui
mlabieniec Apr 7, 2018
bb50b90
Update authentication_guide.md
mbahar Apr 10, 2018
11f2dcc
merge from upstream
powerful23 Apr 10, 2018
4903830
update to withOAuth
powerful23 Apr 10, 2018
27d8e26
Merge remote-tracking branch 'upstream/master' into cognito-hosted-ui
powerful23 Apr 10, 2018
7078fbc
Update authentication_guide.md
mbahar Apr 11, 2018
d7b7e6e
mionr change
powerful23 Apr 12, 2018
be0225d
merge upstream
powerful23 Apr 13, 2018
1dcd5f9
mionr change
powerful23 Apr 13, 2018
73fa122
mionr change
powerful23 Apr 13, 2018
cbddcc1
docs update
powerful23 Apr 13, 2018
f3e65aa
change customAttrs to options
powerful23 Apr 13, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions docs/media/authentication_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,94 @@ const federated = {

There is also `withGoogle`, `withFacebook`, `withAmazon` components, in case you need to customize a single provider.

### Cognito Hosted UI

Cognito hosted UI provides general availability of a Built-in Customizable User Experience for Sign-in, OAuth 2.0 Support, and Federation with Facebook, Login with Amazon, Google, and SAML providers for User Pools.

#### Setup your Cognito App Client

First you need to setup your App Client in the Cognito User Pool console.

* Go to: App integration -> App client settings
* Select Identity Providers
* Input your Callback URL and Sign out URL.
* Select OAuth Flows (Authorization code grant is the recommended choice for security reasons)
* Choose OAuth Scopes

* Go to: App integration -> Domain name
* Input the domain prefix for sign-up and sign-in pages hosted by Cognito

To add federation provider

* Go to: Federation -> Identity providers
* Select the federated identity provider
* Input required configuration like App Id, App secret, Authorized scope
* Set the Oauth Redirected URI in your Facebook/Google app's setting page to:

```https://your-domain-prefix.auth.us-east-1.amazoncognito.com/oauth2/idpresponse```

* Go to Federation -> Attribute mapping
* Map Federation Provider attributes to corresponding User pool attributes. Please make sure at least Email is correctly mapped.

* Don't forget to select this provider in the App client settings
#### Integrate it into your App

* You need to pass your hosted ui options into Amplify:
```js
import Amplify from 'aws-amplify';

const hostedUIOptions = {
AppWebDomain : 'your-domain-prefix.auth.us-east-1.amazoncognito.com', // Domain name
TokenScopesArray : ['phone', 'email', 'profile', 'openid', 'aws.cognito.signin.user.admin'], // Authorized scopes,
RedirectUriSignIn : 'http://localhost:3000/', // Callback URL
RedirectUriSignOut : 'http://localhost:3000/', // Sign out URL
AdvancedSecurityDataCollectionFlag : true, // indicating if the data collection is enabled to support cognito advanced security features. By default, this flag is set to true.
ResponseType: 'code' // 'code' for Authorization code grant, 'token' for Implicit grant
}

Amplify.configure({
Auth: {
// other configurations...
// ....
hostedUIOptions: hostedUIOptions
},
// ...
});
```

* If you are using ```aws-amplify-react```:
* You will see a button ```Sign in with AWS``` showed up in your login page when you are using the HOC ```withAuthenticator``` or using the ```Authenticator``` component.
* You can also import the HOC provided and wrap your own component with it, for example:
```jsx
import { withCognito } from 'aws-amplify-react';

class MyComp extends React.Component {
// ...
render() {
return(
<SignInButton onClick={props.cognitoSignIn}>
</SignInButton>
)
}
}

export default withCognito(MyComp);
```

* If you are NOT using ```aws-amplify-react```:
* you need to construct the url yourself:
```js
const config = Auth.configure();
const {
AppWebDomain,
RedirectUriSignIn,
RedirectUriSignOut,
ResponseType } = config.hostedUIOptions;
const clientId = config.userPoolWebClientId;
const url = 'https://' + AppWebDomain + '/login?redirect_uri=' + RedirectUriSignIn + '&response_type=' + ResponseType + '&client_id=' + clientId;
window.location.assign(url);
```

### Enabling MFA (Multi-Factor Authentication)

Multi-factor authentication (MFA) increases security for your app by adding an authentication method and not relying solely on username (or alias) and password. AWS Amplify uses Amazon Cognito to provide MFA. Please see [Amazon Cognito Developer Guide](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-mfa.html) for more information about setting up MFA in Amazon Cognito.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`withCognito test render test render correctly 1`] = `
<MockComp
cognitoSignIn={[Function]}
/>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, { Component } from 'react';
import withCognito, { CognitoButton } from '../../../src/Auth/Provider/withCognito';
import { SignInButton, Button } from '../../../src/AmplifyUI';
import { Auth } from 'aws-amplify';

describe('withCognito test', () => {
describe('render test', () => {
test('render correctly', () => {
const MockComp = class extends Component {
render() {
return <div />;
}
}

const Comp = withCognito(MockComp);
const wrapper = shallow(<Comp/>);
expect(wrapper).toMatchSnapshot();
});
});

describe('signIn test', () => {
test('happy case with connected response', () => {
const MockComp = class extends Component {
render() {
return <div />;
}
}

const spyon = jest.spyOn(Auth, 'configure').mockImplementationOnce(() => {
return {
hostedUIOptions: {
AppWebDomain: 'domain',
RedirectUriSignIn: 'redirectUriSignIn',
RedirectUriSignOut: 'redirectUriSignOut',
ResponseType: 'responseType'
},
userPoolWebClientId: 'userPoolWebClientId'
}
})
const Comp = withCognito(MockComp);
const wrapper = shallow(<Comp/>);
const comp = wrapper.instance();

comp.signIn();

spyon.mockClear();
});
});
});
18 changes: 16 additions & 2 deletions packages/aws-amplify-react/src/Auth/FederatedSignIn.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
import {
GoogleButton,
FacebookButton,
AmazonButton
AmazonButton,
CognitoButton
} from './Provider';

const logger = new Logger('FederatedSignIn');
Expand Down Expand Up @@ -49,21 +50,34 @@ export class FederatedButtons extends Component {
/>
}

cognito(cognito_auth) {
if (!cognito_auth) { return null; }
const { theme, onStateChange } = this.props;
return <CognitoButton
authData={cognito_auth.authData}
label={cognito_auth.label}
theme={theme}
onStateChange={onStateChange}
/>
}


render() {
const { authState } = this.props;
if (!['signIn', 'signedOut', 'signedUp'].includes(authState)) { return null; }

const federated = this.props.federated || {};
if (JS.isEmpty(federated)) { return null; }

const { google_client_id, facebook_app_id, amazon_client_id } = federated;
const { google_client_id, facebook_app_id, amazon_client_id, cognito_auth } = federated;

const theme = this.props.theme || AmplifyTheme;
return (
<ActionRow theme={theme}>
{this.google(google_client_id)}
{this.facebook(facebook_app_id)}
{this.amazon(amazon_client_id)}
{this.cognito(cognito_auth)}
</ActionRow>
)
}
Expand Down
4 changes: 3 additions & 1 deletion packages/aws-amplify-react/src/Auth/Provider/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import React, { Component } from 'react';
import withGoogle from './withGoogle';
import withFacebook from './withFacebook';
import withAmazon from './withAmazon';
import withCognito from './withCognito';

export { default as withGoogle, GoogleButton } from './withGoogle';
export { default as withFacebook, FacebookButton } from './withFacebook';
export { default as withAmazon, AmazonButton } from './withAmazon';
export { default as withCognito, CognitoButton } from './withCognito';

export function withFederated(Comp) {
const Federated = withAmazon(withGoogle(withFacebook(Comp)));
const Federated = withCognito(withAmazon(withGoogle(withFacebook(Comp))));

return class extends Component {
render() {
Expand Down
47 changes: 47 additions & 0 deletions packages/aws-amplify-react/src/Auth/Provider/withCognito.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { Component } from 'react';

import { Auth, Logger } from 'aws-amplify';
import AmplifyTheme from '../../AmplifyTheme';
import { SignInButton } from '../../AmplifyUI';

const logger = new Logger('withCognito');

export default function withCognito(Comp) {
return class extends Component {
constructor(props) {
super(props);
this.signIn = this.signIn.bind(this);
this.state = {};
}

signIn() {
const config = Auth.configure();
const {
AppWebDomain,
RedirectUriSignIn,
RedirectUriSignOut,
ResponseType } = config.hostedUIOptions;
const clientId = config.userPoolWebClientId;
const url = 'https://' + AppWebDomain + '/login?redirect_uri=' + RedirectUriSignIn + '&response_type=' + ResponseType + '&client_id=' + clientId;
window.location.assign(url);
}

render() {
return (
<Comp {...this.props} cognitoSignIn={this.signIn} />
)
}
}
}

const Button = (props) => (
<SignInButton
id="cognito_signin_btn"
onClick={props.cognitoSignIn}
theme={props.theme || AmplifyTheme}
>
{props.label || 'Sign in with AWS'}
</SignInButton>
)

export const CognitoButton = withCognito(Button);
26 changes: 15 additions & 11 deletions packages/aws-amplify/__tests__/Auth/auth-unit-test-rn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,23 +148,27 @@ import Cache from '../../src/Cache';
import { CognitoUserPool, CognitoUser, CognitoUserSession, CognitoIdToken, CognitoAccessToken } from 'amazon-cognito-identity-js';
import { CognitoIdentityCredentials } from 'aws-sdk';

const authOptions: AuthOptions = {
userPoolId: "awsUserPoolsId",
userPoolWebClientId: "awsUserPoolsWebClientId",
region: "region",
identityPoolId: "awsCognitoIdentityPoolId"
const authOptions = {
Auth: {
userPoolId: "awsUserPoolsId",
userPoolWebClientId: "awsUserPoolsWebClientId",
region: "region",
identityPoolId: "awsCognitoIdentityPoolId"
}
}

const authOptionsWithNoUserPoolId = {
userPoolId: null,
userPoolWebClientId: "awsUserPoolsWebClientId",
region: "region",
identityPoolId: "awsCognitoIdentityPoolId"
Auth: {
userPoolId: null,
userPoolWebClientId: "awsUserPoolsWebClientId",
region: "region",
identityPoolId: "awsCognitoIdentityPoolId"
}
}

const userPool = new CognitoUserPool({
UserPoolId: authOptions.userPoolId,
ClientId: authOptions.userPoolWebClientId
UserPoolId: authOptions.Auth.userPoolId,
ClientId: authOptions.Auth.userPoolWebClientId
});

const idToken = new CognitoIdToken({IdToken: 'idToken'});
Expand Down
Loading