できること
認証はuserPool、認可はIdentitiyPoolで行われ、それぞれ別のリソース
認証
- Cognitoで管理されているユーザー情報で認証ができる
- 外部プロバイダー(Azure、Google、Facebook)と連携が可能
- ユーザー認証が成功すると、トークンが発行され、アプリケーション側でトークンの検証を行うことで認証機能をつくることができる
- UserPoolで行われる
認可
- 一時的な権限を与える
- チケットを渡すイメージ
- Cognitoではグループや属性ごとにIAMRoleを割り振ったりすることができる
- IndentityPoolで行われる
Cognito設定
サンプルコード
main.go
package main
import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cognitoidentityprovider"
"github.com/golang-jwt/jwt/v4"
)
type Tokens struct {
Id string
Access string
Refresh string
}
func main() {
tokens := cognitoAuth()
inspectionjwt(tokens.Id)
}
func inspectionjwt(tokenString string) {
CustomClaims := jwt.MapClaims{}
// tokenからjwt形式へ変換する
token, _ := jwt.ParseWithClaims(tokenString, CustomClaims, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, errors.New("unexpected signing method")
}
return []byte("test"), nil
})
// 一度JSONへ変換
jsonString, err := json.Marshal(token.Claims)
if err != nil {
fmt.Println("JSON Marshal error: ", err)
}
// Cognitoから返されるTokenの構造に合わせてStructを定義する
type JwtClaims struct {
Email string `json:"email"`
User string `json:"cognito:username"`
}
var jwtClaims JwtClaims
// 定義したStructへ変換
if err := json.Unmarshal(jsonString, &jwtClaims); err != nil {
fmt.Println("jsonunmarshal error")
}
// メールアドレス、名前を表示
fmt.Println(jwtClaims.Email)
fmt.Println(jwtClaims.User)
}
func cognitoAuth() Tokens {
if len(os.Args) != 3 {
log.Fatal("invalid args")
}
name := os.Args[1]
password := os.Args[2]
params := &cognitoidentityprovider.AdminInitiateAuthInput{
AuthFlow: aws.String(cognitoidentityprovider.AuthFlowTypeAdminNoSrpAuth),
AuthParameters: map[string]*string{
"USERNAME": aws.String(name),
"PASSWORD": aws.String(password),
},
ClientId: aws.String(os.Getenv("CLIENT_ID")),
UserPoolId: aws.String(os.Getenv("USER_POOL_ID")),
}
client := cognitoidentityprovider.New(
session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
})),
)
res, err := client.AdminInitiateAuth(params)
if err != nil {
log.Print("AdminAuth Error")
log.Fatal(err)
}
if res == nil || res.AuthenticationResult == nil || res.AuthenticationResult.IdToken == nil {
log.Fatal("failed to login")
}
var tokens Tokens
tokens.Id = *res.AuthenticationResult.IdToken
tokens.Access = *res.AuthenticationResult.AccessToken
tokens.Refresh = *res.AuthenticationResult.RefreshToken
return tokens
}
実行
go run main.go yuta password
出力
yuta@vamdemicsystem.black
kujirai
トークン
IDトークン、Accessトークン、リフレッシュトークンの3つが発行される
IDトークン
- 認証されたユーザーの情報がJWT形式で含まれている
- グループや属性などを拾うことができる
- デフォルト1時間でExpireする
- アプリケーションで認証機能を作る場合は、基本的にこれを使う
アクセストークン
- 自分のグループや属性などプロパティ的なものを変更するために必要なトークン
- 認証されたユーザーに関するクレーム、グループのリスト、スコープのリストなどが含まれる
- IDトークンと同様にJWTで表現される
- IDトークンとは署名するキーが異なるため、Kidが異なる
- デフォルト1時間でExpireする
- https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html
リフレッシュートークン
- IDトークンとアクセストークンを再発行できるトークン
- 数時間~数日単位で期限を設定することができる
- トークンが切れるとユーザーは再認証を求められることになるが、リフレッシュートークンを利用するとこでユーザーに操作させることなく、トークンを再発行させることができる
参考
https://tech.anti-pattern.co.jp/golang-cognito/
https://dev.classmethod.jp/articles/study-tokens-of-cognito-user-pools/
https://zenn.dev/takamin55/articles/8442a7583fe5fa