@pcgbros/cognito-sdk-frontend
v2.1.0
Published
pcg aws cognito process (frontend)
Downloads
5
Readme
pbplus-cognito-frontend-sdk
安裝
npm 套件需求:
@pcgbros/session-sdk-frontend ^2.1.2 react ^16.5.2 react-dom ^16.5.2 react-redux ^5.0.7 react-router-dom ^4.3.1
使用 cognito (一):combineReducer
cognito sdk 需要 session sdk,這兩個 sdk 都和 redux 相依,第一步就是將 combineReducers 傳入的物件中加入這兩個 reducer。
import { PBPLUS_SESSION_REDUCER, pbplusSessionReducer } from '@pcgbros/session-sdk-frontend';
import { combineReducers } from 'redux';
import { PBPLUS_COGNITO_REDUCER, pbplusCognitoReducer } from '@pcgbros/cognito-sdk-frontend';
export default combineReducers({
[PBPLUS_SESSION_REDUCER]: pbplusSessionReducer,
[PBPLUS_COGNITO_REDUCER]: pbplusCognitoReducer
});
使用 cognito (二):
使用 cognito function 傳入 (cognitoConfig)(App Component),搭配 compose 可以把 HOC 過多層的寫法變得更簡略。
cognito sdk 需要 session id 作為現在使用者登入狀態的識別碼, sessionStart 負責初始現在使用者的 session id, cognito 才能依據 session id 向 server 請求登入資訊, 當然這兩個 sdk 都需要準備好各自的 config。
import sessionStart from '@pcgbros/session-sdk-frontend';
import cognito from '@pcgbros/cognito-sdk-frontend';
import React, { Component } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import Navigator from './Navigator.js';
import RouteComponent from './RouteComponent.js';
export class App extends Component{
render() {
const { isLoading } = this.props;
return (
<React.Fragment>
<Navigator />
<RouteComponent />
{
isLoading ?
<i className="fa fa-2x fa-circle-o-notch fa-spin loading-icon"></i> :
null
}
</React.Fragment>
);
}
}
const sessionConfig = {
baseURL: process.env.PBPLUS_SESSION.BASE_URL,
clientId: process.env.PBPLUS_SESSION.CLIENT_ID,
defaultSessionId: process.env.PBPLUS_SESSION.DEFAULT_SESSION_ID,
};
const cognitoConfig = {
authDomain: process.env.AWS_COGNITO.AUTH_DOMAIN,
userPoolClientId: process.env.AWS_COGNITO.USER_POOL_CLIENT_ID,
cognitoBaseURL: process.env.AWS_COGNITO.BASE_URL
};
function mapStateToProps(store) {
const { app } = store;
const { isLoading } = app;
return {
isLoading,
};
}
export default compose(
sessionStart(sessionConfig),
cognito(cognitoConfig),
withRouter,
connect(mapStateToProps)
)(App);
關於 cognito
cognito 會有兩個預設行為:
1 若從 cognito 登入頁面登入完成轉導回來時,會向 server 送出現在 session id 為登入狀態的請求,並轉導至到跳至 cognito 登入畫面前的頁面。
2 向 servier 請求現在 session id 的登入狀態,並寫到 reducer 中,可以藉由 getLoginStatusFromStore
取得現在的登入資訊。
cognito settings:
必填屬性: authDomain cognitoBaseURL userPoolClientId
getLoginStatusFromStore
取得 reducer 中的登入資訊
defaultState = {
// 使用者是否為登入狀態
isLoggedIn: false,
// 向 server 請求登入狀態流程是否結束
isLoginStatusInitialized: false,,
// 向 server 請求登入的狀態 flag
isFetchingLoginStatus: false,
// 使用者的 cognito email
email: '',
// 使用者的 cognito username
username: ''
};
// SomeComponent.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getLoginStatusFromStore } from '@pcgbros/cognito-sdk-frontend';
export class SomeComponent extends Component {
render() {
const { isLoggedIn, email } = this.props;
return (
<main>
<h1>登入狀態: { isLoggedIn ? '已登入' : '未登入' }</h1>
<h1>使用者 email: {email}</h1>
</main>
);
}
}
export default connect(store => {
const loginStatus = getLoginStatusFromStore(store);
return {
isLoggedIn: loginStatus.isLoggedIn,
email: loginStatus.email
};
})(SomeComponent);
Other Actions
fetchLoginStatus
此為 redux action,手動取得現在 session id 對應的登入狀態,需傳入 cognito base url。
sample code:
import { fetchLoginStatus } from '@pcgbros/cognito-sdk-frontend';
dispatch(fetchLoginStatus(cognitoBaseUrl))
logout
此為 redux action,手動登出,這個 action 可以做四件事:
1 向 redis server 送出刪除 session 的請求 2 清空 cookie 的 session id 3 將 cognito reducer 中 loginStatus 的 isLoggedIn email username 設定為:
loginStatus = {
isLoggedIn: false,
email: '',
username: ''
}
其他 flag 表留原本狀態。
4 自動轉導至 cognito 登入頁面,這個行為可以藉由傳入物件的 redirectToLoginPageAfterLogout
property (boolean) 控制是否執行轉導。
sample code:
import { logout } from '@pcgbros/cognito-sdk-frontend';
const redirectArgs = {
// config 設定的 cognito auth domain
authDomain,
// config 設定的 cognito userPoolClientId
userPoolClientId,
// 非必填,預設為 true
redirectToLoginPageAfterLogout
};
dispatch(logout(sessionBaseUrl, redirectArgs))
resetLoginStatus
此為 redux action,手動重置 loginStatus 為初始狀態:
defaultState = {
isLoggedIn: false,
isLoginStatusInitialized: false,,
isFetchingLoginStatus: false,
email: '',
username: ''
};
sample code:
import { resetLoginStatus } from '@pcgbros/cognito-sdk-frontend';
dispatch(resetLoginStatus())
redirectToLoginPage
手動轉導至登入頁,直接給參數呼叫即可,這不是 redux action。
sample code:
const redirectArgs = { authDomain: COGNITO_AUTH_DOMAIN, userPoolClientId: COGNITO_USER_POOL_CLIENT_ID };
redirectToLoginPage(redirectArgs);
將上面這些 actions 寫在 React Component 裡的 sample code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
logout,
getLoginStatusFromStore,
fetchLoginStatus,
redirectToLoginPage
} from '@pcgbros/cognito-sdk-frontend';
const { AUTH_DOMAIN, USER_POOL_CLIENT_ID, BASE_URL } = process.env.AWS_COGNITO;
const sessionBaseUrl = process.env.PBPLUS_SESSION.BASE_URL;
export class SomeComponent extends Component {
constructor(props) {
super(props);
this.logoutWithoutRedirect = this.logoutWithoutRedirect.bind(this);
this.fetchLoginStatus = this.fetchLoginStatus.bind(this);
this.redirectToLoginPage = this.redirectToLoginPage.bind(this);
this.logoutWithRedirect = this.logoutWithRedirect.bind(this);
}
logoutWithoutRedirect() {
const redirectArgs = {
authDomain: AUTH_DOMAIN,
userPoolClientId: USER_POOL_CLIENT_ID,
redirectToLoginPageAfterLogout: false
};
this.props.logout(sessionBaseUrl, redirectArgs);
}
logoutWithRedirect() {
const redirectArgs = {
authDomain: AUTH_DOMAIN,
userPoolClientId: USER_POOL_CLIENT_ID
};
this.props.logout(sessionBaseUrl, redirectArgs);
}
fetchLoginStatus() {
this.props.fetchLoginStatus(BASE_URL);
}
redirectToLoginPage() {
const redirectArgs = { authDomain: AUTH_DOMAIN, userPoolClientId: USER_POOL_CLIENT_ID };
redirectToLoginPage(redirectArgs);
}
render() {
const { loginStatus } = this.props;
if (!loginStatus.isLoginStatusInitialized) {
return null;
}
return (
loginStatus.isLoggedIn ?
<div>
<a style={{display: 'block', textDecoration: 'underline', cursor: 'pointer'}} onClick={this.logoutWithoutRedirect}>登出 後在原頁</a>
<a style={{display: 'block', textDecoration: 'underline', cursor: 'pointer'}} onClick={this.logoutWithRedirect}>登出 後回主頁</a>
<a style={{display: 'block', textDecoration: 'underline', cursor: 'pointer'}} onClick={this.fetchLoginStatus}>重新抓取登入資訊,可以在 form submit 的時候重新驗證登入資訊</a>
</div>
:
<div>
<a style={{display: 'block', textDecoration: 'underline', cursor: 'pointer'}} onClick={this.redirectToLoginPage}>登入</a>
<a style={{display: 'block', textDecoration: 'underline', cursor: 'pointer'}} onClick={this.fetchLoginStatus}>重新抓取登入資訊,可以在 form submit 的時候重新驗證登入資訊</a>
</div>
);
}
}
export default withRouter(connect(store => {
const loginStatus = getLoginStatusFromStore(store);
return {
loginStatus
};
}, dispatch => {
return {
logout: (sessionBaseUrl, redirectArgs) => {
return dispatch(logout(sessionBaseUrl, redirectArgs));
},
fetchLoginStatus: (cognitoBaseURL) => {
return dispatch(fetchLoginStatus(cognitoBaseURL));
},
};
})(SomeComponent));