The AWS Amplify Auth module provides Authentication APIs and building blocks to developers wishing to use pre-build components or scaffold out custom UX. Depending on needs, Auth can be integrated at different levels.
Please refer to this Guide for general setup. Here are Authentication specific setup.
To create a project fully functioning with the Auth category.
$ npm install -g awsmobile-cli
$ cd my-app
$ awsmobile init
$ awsmobile enable user-signin
$ awsmobile push
In your project i.e. App.js:
import Amplify, { Auth } from 'aws-amplify';
import aws_exports from './aws-exports';
Amplify.configure(aws_exports);
import Amplify from 'aws-amplify';
Amplify.configure({
Auth: {
// REQUIRED - Amazon Cognito Identity Pool ID
identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab',
// REQUIRED - Amazon Cognito Region
region: 'XX-XXXX-X',
// OPTIONAL - Amazon Cognito User Pool ID
userPoolId: 'XX-XXXX-X_abcd1234',
// OPTIONAL - Amazon Cognito Web Client ID
userPoolWebClientId: 'XX-XXXX-X_abcd1234',
// OPTIONAL - Enforce user authentication prior to accessing AWS resources or not
mandatorySignIn: false
}
});
APIs can be used in any Javascript framework. API Reference has full list. Below are some examples to get started.
import { Auth } from 'aws-amplify';
import './aws-exports' // <-- use this if you used the cli to bootstrap your project
Auth.signIn(username, password)
.then(user => console.log(user))
.catch(err => console.log(err));
// If MFA enabled, keep the user object from sign in, collect confirmation code, and then
Auth.confirmSignIn(user, code)
.then(data => console.log(data))
.catch(err => console.log(err));
import { Auth } from 'aws-amplify';
Auth.signUp({
username,
password,
attributes: {
email, // optional
phone_number, // optional - E.164 number convention
// other custom attributes
},
validationData: [] //optional
})
.then(data => console.log(data))
.catch(err => console.log(err));
// Collect confirmation code, then
Auth.confirmSignUp(username, code)
.then(data => console.log(data))
.catch(err => console.log(err));
import { Auth } from 'aws-amplify';
Auth.signOut()
.then(data => console.log(data))
.catch(err => console.log(err));
import { Auth } from 'aws-amplify';
Auth.forgotPassword(username)
.then(data => console.log(data))
.catch(err => console.log(err));
// Collect confirmation code and new password, then
Auth.forgotPasswordSubmit(username, code, new_password)
.then(data => console.log(data))
.catch(err => console.log(err));
Return a CognitoUserSession
which contains JWT accessToken
, idToken
, and refreshToken
.
let session = Auth.currentSession();
// CognitoUserSession => { idToken, refreshToken, accessToken }
For React and React Native apps, the simplest way to add Auth flows into your app is to use withAuthenticator
.
Just add these two lines to your App.js
:
import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native';
...
export default withAuthenticator(App);
Now your app is guarded by complete Auth flow. Only signed in user can access the app.
You can enable federated Identity login by specifying federated option.
const AppWithAuth = withAuthenticator(App);
const federated = {
google_client_id: '',
facebook_app_id: '',
amazon_client_id: ''
};
ReactDOM.render(<AppWithAuth federated={federated}/>, document.getElementById('root'));
NOTE: Federated Identity HOCs are not yet available on React Native
The default withAuthenticator
renders just the App component after a user is signed in, preventing interference with your app. Then question comes, how does the user sign out?
To expose this, set the second parameter to true, which means includeGreetings = true
. It will put a greeting row on top of your app.
export default withAuthenticator(App, { includeGreetings: true });
The withAuthenticator
HOC essentially just wraps Authenticator
component. You can use the Authenticator
directly to give yourself more customization options.
App.js
import { Authenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native'
...
class AppWithAuth extends Component {
render(){
return (
<div>
<Authenticator>
<App />
</Authenticator>
</div>
);
}
}
export default AppWithAuth;
In the above example you'll see the App rendered even before the user is signed in. This is easy to change.
When inside Authenticator
, the App component will receive a few properties.
authState is the current authentication state (a string):
signIn
signUp
confirmSignIn
confirmSignUp
forgotPassword
verifyContact
signedIn
authData - additional data within authState, when signedIn
, it is a user
object
With that, to control when to render App component, simply add
this._validAuthStates = ['signedIn'];
to the component's constructor, then implement showComponent(theme) {}
in lieu of the typical
render() {}
method.
Authenticator
is designed as a container, which contains a number of Auth components. Each component does one job, for example SignIn, SignUp etc.
You can compose your own Authenticator, but you must set hideDefault={true}
.
For example, this Authenticator only shows Greetings component which has a Sign Out button:
<Authenticator hideDefault={true}>
<Greetings />
</Authenticator>
The Greetings component has messages for two different auth states: signedIn, and signedOut. To customize the messages, set properties inGreeting
and outGreeting
using a string or function.
<Authenticator hideDefault={true}>
<Greetings
inGreeting={(username) => 'Hello ' + username}
outGreeting="Come back"
/>
</Authenticator>
You may write your own Auth UI. To do this your component will leverage the following properties:
- authState
- authData
- onStateChange
This example creates an AlwaysOn
Auth UI, which shows the current auth state.
import { Authenticator, SignIn, SignUp, ConfirmSignUp, Greetings } from 'aws-amplify-react';
const AlwaysOn = (props) => {
return (
<div>
<div>I am always here to show current auth state: {props.authState}</div>
<button onClick={() => props.onStateChange('signUp')}>Show Sign Up</button>
</div>
)
}
handleAuthStateChange(state) {
if (state === 'signedIn') { /* GO TO Main Page */ }
}
render() {
return (
<Authenticator hideDefault={true} onStateChange={this.handleAuthStateChange}>
<SignIn/>
<SignUp/>
<ConfirmSignUp/>
<Greetings/>
<AlwaysOn/>
</Authenticator>
)
}
Note: Our federated identity components so far only support Google, Facebook and Amazon, only available for React. Building is in progress.
Setup guide is here.
After setup. Just add Google client_id
, Facebook app_id
and/or Amazon client_id
to Authenticator
const federated = {
google_client_id: '',
facebook_app_id: '',
amazon_client_id: ''
};
return (
<Authenticator federated={federated}>
)
Every app may have a slightly different UI. Use withFederated
. There is also withGoogle
, withFacebook
, withAmazon
if you just need a single provider.
import { withFederated } from 'aws-amplify-react';
const Buttons = (props) => (
<div>
<img
onClick={props.googleSignIn}
src={google_icon}
/>
<img
onClick={props.facebookSignIn}
src={facebook_icon}
/>
<img
onClick={props.amazonSignIn}
src={amazon_icon}
/>
</div>
)
const Federated = withFederated(Buttons);
...
const federated = {
google_client_id: '',
facebook_app_id: '',
amazon_client_id: ''
};
<Federated federated={federated} onStateChange={this.handleAuthStateChange} />
You can pass in any user attributes during sign up:
Auth.signUp({
'username': 'jdoe',
'password': 'mysecurerandompassword#123',
'attributes': {
'email': 'me@domain.com',
'phone_number': '+12128601234', // E.164 number convention
'first_name': 'Jane',
'last_name': 'Doe',
'nick_name': 'Jane'
}
});
You can retrieve user attributes:
let user = await Auth.currentAuthenticatedUser();
You can then update the user attributes:
let result = await Auth.updateUserAttributes(user, {
'email': 'me@anotherdomain.com',
'last_name': 'Lastname'
});
console.log(result); // SUCCESS
If you change the email address you will receive a confirmation code to that email and you can confirm it with the code:
let result = await Auth.verifyCurrentUserAttributeSubmit('email', 'abc123');
Amplify UI components are theme based. Check the AmplifyTheme.js
file for default styling.
You may want to create your own theme, and then pass to Amplify components.
import MyTheme from './MyTheme';
<Authenticator theme={MyTheme} />
Alternatively, override AmplifyTheme
:
import { AmplifyTheme } from 'aws-amplify-react';
const MySectionHeader = Object.assign({}, AmplifyTheme.sectionHeader, { background: 'orange' });
const MyTheme = Object.assign({}, AmplifyTheme, { sectionHeader: MySectionHeader });
<Authenticator theme={MyTheme} />
Theme example can be found here
During authentication flows, there are some error messages returned from server. Amplify provides a simple way of customizing error messages with a messageMap
callback.
The function simply takes the original message as arguments and then outputs the desired message. Check AmplifyMessageMap.js
to see how Amplify makes the map function.
const map = (message) => {
if (/incorrect.*username.*password/i.test(message)) {
return 'Incorrect username or password';
}
return message;
}
<Authenticator errorMessage={map} />
You may notice in AmplifyMessageMap.js
it also handles internationalization. The topic is covered in I18n Guide