Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

React.jsとAWS(cognito)の連携

$
0
0

何をする?

reactコンポーネントからAWSのcognitoにユーザ登録を行い、サインインを行います。

cognitoについて

アプリやwebサービスの認証基盤です。認証ロジックだけAWSに託します。
サービス提供者はログイン情報を保持することなく認証結果のみを受け取ります。
また、cognitoを介して様々なAWSサービスが使えるようになります。
詳細は公式ドキュメントを参照ください。
公式ドキュメント

バージョン

  • node.js 10.15.3
  • react.js ^16.12.0
  • material-ui ^0.20.2
  • amazon-cognito-identity-js ^3.0.15

準備

awsへの連携にはamazon-cognito-identity-jsを使います。

 npm install --save amazon-cognito-identity-js

詳細はこちらを参照ください。
github公式ページ

ユーザプールの作成

userpool.png

アプリクライアント.png

ユーザプール > ユーザとグループ
にアカウント情報が蓄積されます。
プール ARNとプール IDとアプリクライアントIDはプログラムで使用します。
また、今回はサインイン時の二段階認証にEメールを利用します。

IDプールの作成

IDpool.png

IDプールの編集.png

ユーザプールへの登録時にIDプールにも情報を登録します。
これにより、登録ユーザはIDプールを介して他のAWSサービスを利用できるようになります。
IDプールのIDはプログラムで使用します。

これでcognitoを使用する準備ができました。
次にアプリケーションとcognitoを連携します。

該当のプログラム

サインイン画面

まずはreact側でユーザIDとパスワードとEメールアドレスを入力する画面を作成。

signin.js
importReactfrom'react';importPropTypesfrom'prop-types';import{withStyles,createMuiTheme,MuiThemeProvider}from'@material-ui/core/styles';importButtonfrom'@material-ui/core/Button';import{connect}from"react-redux"importFormControlfrom'@material-ui/core/FormControl';importInputfrom'@material-ui/core/Input';importInputLabelfrom'@material-ui/core/InputLabel';import{compose}from'redux'importGridfrom'@material-ui/core/Grid';importCognitoAuthfrom'aws'conststyles=theme=>({contents:{margin:'150px auto 0 ',maxWidth:'1260px',},formContents:{margin:'0 auto',maxWidth:'480px'},formControl:{display:'block',width:'100%'},btn:{marginTop:'20px',}});functiontypographyV1Theme(theme){returncreateMuiTheme({...theme,typography:{useNextVariants:false,},});}classSignInextendsReact.Component{constructor(props){super(props);this.state={password:'',user_id:'',email:'',errors:[],};}goError=async(e)=>{awaitthis.setState({errors:(e.message||JSON.stringify(e))})awaitconsole.log("エラー:"+this.state.errors)};goNext=async()=>{try{awaitthis.props.history.push({pathname:'/activate',state:{user_name:this.state.user_id,password:this.state.password,email:this.state.email,user_id:this.state.user_id}})}catch(e){this.goError(e)}};signInCognito=async()=>{awaitalert(this.state.user_id)awaitCognitoAuth.signIn(this.state.user_id,this.state.password,this.state.email).then(this.goNext).catch(this.goError)};render(){const{classes,dispatchAddValue}=this.props;return(<MuiThemeProvidertheme={typographyV1Theme}><divclassName={classes.contents}><p>お名前をメールアドレスを入力してください。</p>
</div>
<divclassName={classes.formContents}><Gridcontainerspacing={16}><Griditemxs={12}sm={12}><FormControlclassName={classes.formControl}><InputLabelhtmlFor="component-simple">ID</InputLabel>
<Inputid="component-simple"name="user_id"fullWidthdefaultValue={this.state.user_id}/>
</FormControl>
</Grid>
</Grid>
<Gridcontainerspacing={16}><Griditemxs={12}sm={12}><FormControlclassName={classes.formControl}><InputLabelhtmlFor="component-simple">パスワード</InputLabel>
<Inputid="component-simple" name="password"fullWidthdefaultValue={this.state.password}/>
</FormControl>
</Grid>
</Grid>
<Gridcontainerspacing={16}><Griditemxs={12}sm={12}><FormControlclassName={classes.formControl}><InputLabelhtmlFor="component-simple">メールアドレス</InputLabel>
<Inputid="component-simple"name="email"fullWidthdefaultValue={this.state.email}onChange={this.handleChange}/>
</FormControl>
</Grid>
</Grid>
<Gridcontainerspacing={16}><Griditemxs={12}sm={12}>{this.state.errors}</Grid>
</Grid>
<GridclassName={classes.btn}containerspacing={16}><Griditemxs={12}sm={12}><Buttonvariant="contained"color="secondary"fullWidthclassName={classes.fcButton}onClick={this.signInCognito}>次へ</Button>
</Grid>
</Grid>
</div>
</MuiThemeProvider>
);}}SignIn.propTypes={classes:PropTypes.object.isRequired,};exportdefaultcompose(withStyles(styles),connect(mapStateToProps,mapDispatchToProps))(SignIn)

画面はこんなイメージ
サインイン.png

認証

「次へ」ボタンを押すとCognitoAuth.signInが実行され、入力したアドレスに認証コードが届きます。

aws.js
importAWSfrom'aws-sdk'constAmazonCognitoIdentity=require('amazon-cognito-identity-js')constCognitoAuth={signIn:function(userName,password,email=null,phoneNumber=null){returnnewPromise(function(resolve,reject){varuserPoolData={UserPoolId:[ユーザプールID],ClientId:[ユーザプールクライアントID]}varuserPool=newAmazonCognitoIdentity.CognitoUserPool(userPoolData)varattributeList=[];if(email!==null){varattribute={Name:'email',Value:email};attributeList.push(newAmazonCognitoIdentity.CognitoUserAttribute(attribute));}if(phoneNumber!==null){varattribute={Name:'phone_number',Value:phoneNumber};attributeList.push(newAmazonCognitoIdentity.CognitoUserAttribute(attribute));}returnuserPool.signUp(userName,password,attributeList,null,function(err,result){if(err){reject(err)}resolve(result.user)})})},}exportdefaultCognitoAuth;

認証コード入力

届いた認証コードと、ユーザネームと、パスワードを引数にconfirmRegistrationを実行するだけで認証が通ります。そのままログイン処理を実行することでサインイン後は自動的にホーム画面などに遷移させることができます。

aws.js
importAWSfrom'aws-sdk'constAmazonCognitoIdentity=require('amazon-cognito-identity-js')constCognitoAuth={・・・confirmRegistration:function(userName,password,registrationCode){returnnewPromise(function(resolve,reject){varauthenticationData={Username:userName,Password:password}varauthenticationDetails=newAmazonCognitoIdentity.AuthenticationDetails(authenticationData)varuserPoolData={UserPoolId:[ユーザプールID],ClientId:[ユーザプールクライアントID]}varuserPool=newAmazonCognitoIdentity.CognitoUserPool(userPoolData)constuserData={Username:userName,Pool:userPool}varcognitoUser=newAmazonCognitoIdentity.CognitoUser(userData)cognitoUser.setAuthenticationFlowType('USER_PASSWORD_AUTH')cognitoUser.confirmRegistration(registrationCode,true,function(err,result){if(err){reject(err)}resolve(result)})})},}exportdefaultCognitoAuth;

ログイン

aws.js
importAWSfrom'aws-sdk'constAmazonCognitoIdentity=require('amazon-cognito-identity-js')constCognitoAuth={・・・doLogin:function(userName,password){returnnewPromise(function(resolve,reject){letauthenticationData={Username:userName,Password:password};letauthenticationDetails=newAmazonCognitoIdentity.AuthenticationDetails(authenticationData)letuserPoolData={UserPoolId:[ユーザプールID],ClientId:[ユーザプールクライアントID]};letuserPool=newAmazonCognitoIdentity.CognitoUserPool(userPoolData)constuserData={Username:userName,Pool:userPool};letcognitoUser=newAmazonCognitoIdentity.CognitoUser(userData)cognitoUser.setAuthenticationFlowType('USER_PASSWORD_AUTH')cognitoUser.authenticateUser(authenticationDetails,{onSuccess:function(result){AwsAuth.setJwtToken(result.getIdToken().getJwtToken())AWS.config.region=[リージョン]AWS.config.credentials=newAWS.CognitoIdentityCredentials({IdentityPoolId:[IDプールのID],Logins:{[[プールARN]]:result.getIdToken().getJwtToken()}});AWS.config.credentials.clearCachedId()AWS.config.credentials.refresh((error)=>{if(error){reject(error)}else{resolve(result.getIdToken().getJwtToken())}});},onFailure:function(err){console.log(err)reject(err)},mfaRequired:function(result){reject("mfaRequired")},newPasswordRequired(result){reject("newPasswordRequired")},customChallenge(result){reject("customChallenge")}})})}}

まとめ

cognitoを使うことでユーザのログイン情報をDBなどに保持する必要がなくなるのでサービスを提供する側にとっては大きなリスク回避になりますね。また、facebookやtwitterアカウントなどのリソースを利用した認証基盤も簡単に導入できます。


Viewing all articles
Browse latest Browse all 8691

Trending Articles