マイナンバーカードによる署名
このページでは、デジタル認証アプリを使用してマイナンバーカードによる署名を行う方法を説明します。
このステップでは、ユーザーのブラウザからデジタル認証アプリにリダイレクトし、マイナンバーカードを使用した署名を行います。 この処理は、OpenID Connect の認可コードフローという方式を使用して行われます。
シーケンス
実装例
package main
import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"net/url"
)
const (
// デジタル庁から発行されたクライアント IDです。ご自身のクライアント IDで置き換えてください。
clientID = "<YOUR_CLIENT_ID>"
// 認可エンドポイント
authURL = "https://sb-auth-and-sign.go.jp/api/realms/main/protocol/openid-connect/auth"
// 署名トランザクション開始レスポンスで返却された署名トランザクション IDを設定します。
signTxId = "37a52ac8-b232-ebac-a454-04d68916489f"
)
func run() error {
// stateに設定されるランダムな値を生成します。
rawState := make([]byte, 32)
if _, err := rand.Reader.Read(rawState); err != nil {
return fmt.Errorf("failed to generate state: %w", err)
}
state := base64.RawURLEncoding.EncodeToString(rawState)
fmt.Println("state:", state)
// nonceに設定されるランダムな値を生成します。
rawNonce := make([]byte, 32)
if _, err := rand.Reader.Read(rawNonce); err != nil {
return fmt.Errorf("failed to generate nonce: %w", err)
}
nonce := base64.RawURLEncoding.EncodeToString(rawNonce)
fmt.Println("nonce:", nonce)
// code_verifierに設定されるランダムな値を生成します。
cvRaw := make([]byte, 32)
if _, err := rand.Reader.Read(cvRaw); err != nil {
return fmt.Errorf("failed to generate cv: %w", err)
}
cv := hex.EncodeToString(cvRaw)
fmt.Println("cv:", cv)
// code_challengeを生成します。
ccRaw := sha256.Sum256([]byte(cv))
cc := base64.RawURLEncoding.EncodeToString(ccRaw[:])
reqBody := url.Values{}
// 固定値codeを設定する。
reqBody.Set("response_type", "code")
// 署名 API では、openid と sign のスコープが必須
reqBody.Set("scope", "openid sign")
// デジタル認証アプリサービスがクライアントに発行したクライアントID。
reqBody.Set("client_id", clientID)
// レスポンスが返される Redirection URI。
reqBody.Set("redirect_uri", "https://aas.p8n.jp")
// リクエストとコールバックの間で維持されるランダムな値。Cross-Site Request Forgery (CSRF, XSRF) 対策の目的で利用される。
reqBody.Set("state", state)
// Client セッションと ID Token を紐づける文字列。リプレイアタック対策に用いられる。
reqBody.Set("nonce", nonce)
// code_verifier(半角英数字および記号(-.~)からなるランダムな43〜128の文字)をSHA256でハッシュ化したうえで、Base64URL形式にエンコードした値。
reqBody.Set("code_challenge", cc)
// 固定値"S256"を設定する。
reqBody.Set("code_challenge_method", "S256")
// 署名を要求する場合に、署名トランザクション開始レスポンスの署名トランザクションIDを設定する。
reqBody.Set("sign_transaction_id", signTxId)
// 認可エンドポイントの URL を表示します。
fmt.Printf("%s?%s\n", authURL, reqBody.Encode())
return nil
}
func main() {
if err := run(); err != nil {
panic(err)
}
}
実行結果
state: bOnkxOm-z-C4W_Mtuo04YRWrOr8qmN_A-hJl-8xoShU
nonce: LssF5mhV5gA3UkDzx3aPz0BHIRl8PsSYmU0l4eFnpQc
cv: c91f60547f2b8e47890e3a493b56e24b1081e3ff8087636b9add7973e55ddd01
https://sb-auth-and-sign.go.jp/api/realms/main/protocol/openid-connect/auth?client_id=...&code_challenge=xoxprXgC1URrV6m-6co8PRmb87vPnrvLf0f1cqpNGek&code_challenge_method=S256&nonce=LssF5mhV5gA3UkDzx3aPz0BHIRl8PsSYmU0l4eFnpQc&redirect_uri=https%3A%2F%2Faas.p8n.jp&response_type=code&scope=openid+sign&sign_transaction_id=37a52ac8-b232-ebac-a454-04d68916489f&state=bOnkxOm-z-C4W_Mtuo04YRWrOr8qmN_A-hJl-8xoShU
認可リクエストの URL にアクセスすると、以下のような流れで処理が進みます:
- ブラウザにデジタル認証アプリの認証画面が表示されます
- 認証が成功すると、デジタル認証アプリで署名を作成する手続きが始まります
- 署名が完了すると、指定したリダイレクト URI にリダイレクトされます
この実装例の場合、以下のような URL にリダイレクトされます。
https://aas.p8n.jp/?code=AbcdEfgHijkLMNoPqrStuVwXyZ0123456789&state=bOnkxOm-z-C4W_Mtuo04YRWrOr8qmN_A-hJl-8xoShU&session_state=7bc46d4f-7184-4649-9d10-96a03ce50003
次のステップ
マイナンバーカードによる署名が成功したら、次のステップとして認可コードフローによるトークンの取得を行いましょう。
その他、デジタル認証アプリサービス API の使い方やエラーの詳細等については、デジタル認証アプリのマニュアルをご覧ください。