yarn add aws-amplify@preview
# Optional
yarn add hoist-non-react-statics
// libs/withAmplify.js
import * as React from "react";
import { Amplify, withSSRContext } from "aws-amplify";
import hoistNonReactStatics from "hoist-non-react-statics";
const AmplifyContext = React.createContext();
export const useAmplify = () => React.useContext(AmplifyContext);
export const withAmplify = (ComposedComponent) => {
const WithAmplify = (props) => {
const { amplifyConfig, ...rest } = props;
const { Auth } = withSSRContext();
React.useMemo(() => {
Amplify.configure(amplifyConfig);
Auth.configure(amplifyConfig);
}, []);
return (
<AmplifyContext.Provider value={{ amplifyConfig }}>
<ComposedComponent {...rest} />
</AmplifyContext.Provider>
);
};
WithAmplify.getInitialProps = async (appContext) => {
const { Auth } = withSSRContext(appContext.ctx);
const amplifyConfig = {
Auth: {
region: process.env.AWS_AMPLIFY_REGION,
userPoolId: process.env.AWS_AMPLIFY_USER_POOL_ID,
userPoolWebClientId: process.env.AWS_AMPLIFY_USER_POOL_WEB_CLIENT_ID,
mandatorySignIn: true,
authenticationFlowType: process.env.AWS_AMPLIFY_AUTHENTICATION_FLOW_TYPE,
oauth: {
domain: process.env.AWS_AMPLIFY_OAUTH_DOMAIN,
scope: process.env.AWS_AMPLIFY_OAUTH_SCOPE,
redirectSignIn: process.env.AWS_AMPLIFY_OAUTH_REDIRECT_SIGN_IN,
redirectSignOut: process.env.AWS_AMPLIFY_OAUTH_REDIRECT_SIGN_OUT,
responseType: process.env.AWS_AMPLIFY_OAUTH_RESPONSE_TYPE,
},
},
};
if (typeof window === 'undefined') {
Amplify.configure(amplifyConfig);
Auth.configure(amplifyConfig);
}
return {
amplifyConfig,
};
};
return hoistNonReactStatics(WithAmplify, ComposedComponent);
};
Wrap your App with withAmplify
HOC previously created.
// pages/_app.js
import * as React from "react";
import { withAmplify } from "../libs/withAmplify";
const MyApp = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default withAmplify(MyApp);
// pages/login.js
import * as React from "react";
import { withSSRContext } from "aws-amplify";
import Router from "next/router";
const Login = (props) => {
const [state, _setState] = React.useState({
username: "",
password: "",
});
const setState = (newState) => _setState({ ...state, ...newState });
// 👇 Your frontend code is now "SSR-aware", giving the backend access to the current session
const { Auth } = withSSRContext();
React.useEffect(() => {
(async () => {
let user, currentSession;
try {
user = await Auth.currentAuthenticatedUser();
} catch (e) {
console.error("currentAuthenticatedUser error:", e);
}
try {
currentSession = await Auth.currentSession();
} catch (e) {
console.error("currentSession error:", e);
}
// if (currentSession) Router.push("/");
console.log("login.user --", user);
console.log("login.currentSession --", currentSession);
})();
}, []);
const handleChange = (e) => {
setState({ [e.target.id]: e.target.value });
};
const federatedSignIn = () => {
Auth.federatedSignIn();
};
const signIn = async (e) => {
e.preventDefault();
try {
await Auth.signIn(state.username, state.password);
Router.push("/");
} catch (err) {
if (err.code === "InvalidParameterException" || err.code === "NotAuthorizedException") alert("Incorrect username or password.");
else alert(err.message);
}
};
return (
<>
<h1>Login page</h1>
<form onSubmit={signIn}>
<input id="username" type="text" value={state.username} onChange={handleChange} />
<input id="password" type="password" value={state.password} onChange={handleChange} />
<button type="submit" onClick={signIn}>
Sign in
</button>
</form>
<br />
<button onClick={federatedSignIn}>Hosted UI</button>
</>
);
};
export default Login;