Skip to content

Instantly share code, notes, and snippets.

@benclmnt
Last active July 2, 2020 03:16
Show Gist options
  • Save benclmnt/64ea390087e98db86417d0273e290eac to your computer and use it in GitHub Desktop.
Save benclmnt/64ea390087e98db86417d0273e290eac to your computer and use it in GitHub Desktop.
Manual Cognito setup without using amplify-cli (User Pool with social idp)

Setting up manual Cognito User Pool with Social Idp without amplify-cli

Cognito provided 2 different types of identity management solutions, User Pools and Federated Identities.

User Pools

User pools are the default "users" management. You can set them up to login using username & password(default) / email address & password. When a user have registered (and probably verify their email), your application will get a Cognito user object when they signed in. You can extract their email, scope, and 3 JWT tokens (id, access, refresh) from the Cognito user object.

If you use User Pools, you can also have an option to signin using third party like google or facebook. However this is different from federated identities (explained below), just beware of that when googling 😃 . If you use third party in user pools, you will still get back a Cognito User object with the 3 JWT tokens(id, access, refresh). If you need their email (which you probably would because the username will be something like Googleuser_abc1234), make sure to add an Attribute Mapping for email in the Cognito console.

The way User Pools social signin works (from my observation) is from a Hosted UI (AWS provided) or your own ui (like I did), it will go through Cognito and Cognito will redirect you to your social identity provider (can see the callback in the query params). After signing in, the identity will go back to Cognito and your app will be redirected to <REDIRECT_SIGN_IN_URL>?code=<SOME_CODE>, and Amplify will help you take the code from the query string and get a token from Authorization endpoint /oauth2/token and boom, you get the token that can be used for signin (Amplify also automatically logged you in)

Federated Identities

This allows users to use your app without registering themselves as users (and potentially to verify their email yada yada).They instead use their google / facebook identities. Federated Identities object won't give much info about the users like the usual Cognito user object, however. For the google federated identities, you only get their name, email and a link to their public profile picture.

Using Amplify ui react

  • Amplify ui react provides a GoogleSignInButton component. This is used for federated identities signin. If you use this, make sure to add your google_client_id to the button component.
  • In the snippet above, I hack the appearance of a GoogleSignInButton because I used the User Pools social signin.

Resources

export default {
Auth: {
// REQUIRED only for Federated Authentication - Amazon Cognito Identity Pool ID
// identityPoolId: process.env.REACT_APP_AWS_IDENTITYPOOL_ID,
// REQUIRED - Amazon Cognito Region
region: process.env.REACT_APP_AWS_REGION,
// OPTIONAL - Amazon Cognito User Pool ID
userPoolId: process.env.REACT_APP_AWS_USERPOOL_ID,
// OPTIONAL - Amazon Cognito Web Client ID (26-char alphanumeric string)
userPoolWebClientId: process.env.REACT_APP_AWS_USERPOOL_WEBCLIENT_ID,
// OPTIONAL - Enforce user authentication prior to accessing AWS resources or not
mandatorySignIn: true,
// OPTIONAL - Manually set the authentication flow type. Default is 'USER_SRP_AUTH'
// authenticationFlowType: 'USER_PASSWORD_AUTH'
oauth: {
domain: process.env.REACT_APP_AWS_USERPOOL_DOMAIN,
scope: ['email', 'openid', 'profile'],
redirectSignIn:
process.env.REACT_APP_AWS_USERPOOL_REDIRECT_SIGNIN ||
'http://localhost:3001',
redirectSignOut:
process.env.REACT_APP_AWS_USERPOOL_REDIRECT_SIGNOUT ||
'http://localhost:3001',
responseType: 'code',
},
},
};
import React from 'react';
import {
BrowserRouter as Router,
Route,
Switch,
Redirect,
} from 'react-router-dom';
import Amplify, { Auth, Hub } from 'aws-amplify';
import { AmplifySignInButton } from '@aws-amplify/ui-react';
import amplifyConfig from './amplify-config.js';
Amplify.configure(amplifyConfig);
const App = () => {
const [user, setUser] = React.useState(null);
// set up Amplify bus to listen for auth changes
Hub.listen('auth', async ({ payload }) => {
const { data } = payload;
// console.log('A new auth event has happened: ', payload);
switch (payload.event) {
case 'signIn':
setUser(data);
break;
case 'signIn_failure':
break;
case 'signOut':
setUser(null);
break;
default:
break;
}
});
React.useEffect(() => {
// check if user is logged in
Auth.currentAuthenticatedUser().then(
(user) => {
// console.log(user);
setUser(user);
},
() => {}
);
}, []);
const unAuthenticatedApp = (
<div className="amplifyauthboxes">
<div style={{ textAlign: 'center', width: 400 }}>
<h1>Google Oauth App</h1>
<div onClick={() => Auth.federatedSignIn({ provider: 'Google' })}>
<AmplifySignInButton provider="google">
Sign in with Google
</AmplifySignInButton>
</div>
</div>
</div>
);
const authenticatedApp = (
<div>My Secret App</div>
);
return (
<Router>
<Switch>
<Route
exact
path="/"
render={() => {
if (user) return authenticatedApp;
else return unAuthenticatedApp;
}}
/>
<Route render={() => <Redirect to={{ pathname: '/' }} />} />
</Switch>
</Router>
);
};
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment