ネイティブ、モバイル、またはシングルページアプリにログインを追加するには、PKCE を使用する認可コードフローを利用できます。このフローの仕組みと、これを使用すべき理由については、Authorization Code Flow with Proof Key for Code Exchange (PKCE) を参照してください。ネイティブ、モバイル、またはシングルページアプリから API を呼び出す方法については、Call Your API Using Authorization Code Flow with PKCE を参照してください。
PKCE を使用する認可コードフローを実装するには、次のリソースを利用できます。
ログインに成功すると、アプリケーションはユーザーの と にアクセスできるようになります。IDトークンには基本的なユーザープロフィール情報が含まれ、アクセストークンは Auth0 の /userinfo エンドポイントや独自の保護された API の呼び出しに使用できます。IDトークンの詳細については、ID Tokens を参照してください。アクセストークンの詳細については、Access Tokens を参照してください。
アプリを Auth0 に登録します。詳しくは、ネイティブアプリケーションを登録するまたはシングルページ Web アプリケーションを登録するを参照してください。
- アプリケーションの種類に応じて、Application Type で Native または Single-Page App を選択します。
- Allowed Callback URL に
YOUR_CALLBACK_URL を追加します。コールバック URL の形式は、アプリケーションの種類とプラットフォームによって異なります。アプリケーションの種類およびプラットフォームごとの形式について詳しくは、Native/Mobile クイックスタートおよびSingle-Page App クイックスタートを参照してください。
- アプリケーションの Grant Types に 認可コード が含まれていることを確認します。詳しくは、Grant Types を更新するを参照してください。
code_verifier を作成します。これは、後でトークンをリクエストするために Auth0 に送信する、暗号学的にランダムな Base64 エンコード文字列です。
code_verifier の作成アルゴリズムの詳細については、 Proof Key for Code Exchange 仕様のセクション 4.1 Client Creates a Code Verifier を参照してください。
// 依存関係: Node.js cryptoモジュール
// https://nodejs.org/api/crypto.html#crypto_crypto
function base64URLEncode(str) {
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
var verifier = base64URLEncode(crypto.randomBytes(32));
Java の例
// 依存関係: Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/
// Base64クラスをインポートします。
// import org.apache.commons.codec.binary.Base64;
SecureRandom sr = new SecureRandom();
byte[] code = new byte[32];
sr.nextBytes(code);
String verifier = Base64.getUrlEncoder().withoutPadding().encodeToString(code);
// 依存関係: Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/
// Base64クラスをインポートします。
// import org.apache.commons.codec.binary.Base64;
SecureRandom sr = new SecureRandom();
byte[] code = new byte[32];
sr.nextBytes(code);
String verifier = Base64.encodeToString(code, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
var buffer = [UInt8](repeating: 0, count: 32)
_ = SecRandomCopyBytes(kSecRandomDefault, buffer.count, &buffer)
let verifier = Data(buffer).base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
NSMutableData *data = [NSMutableData dataWithLength:32];
int result __attribute__((unused)) = SecRandomCopyBytes(kSecRandomDefault, 32, data.mutableBytes);
NSString *verifier = [[[[data base64EncodedStringWithOptions:0]
stringByReplacingOccurrencesOfString:@"+" withString:@"-"]
stringByReplacingOccurrencesOfString:@"/" withString:@"_"]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];
authorization_code をリクエストするために Auth0 に送信する code_challenge を、code_verifier から生成します。
code_challenge が code_verifier からどのように導出されるかについて詳しくは、OAuth Proof Key for Code Exchange 仕様のセクション 4.2 Client Creates the Code Challenge を参照してください。
JavaScript のサンプル
// 依存関係: Node.js crypto モジュール
// https://nodejs.org/api/crypto.html#crypto_crypto
function sha256(buffer) {
return crypto.createHash('sha256').update(buffer).digest();
}
var challenge = base64URLEncode(sha256(verifier));
// 依存関係: Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/
// Base64クラスをインポートします。
// import org.apache.commons.codec.binary.Base64;
byte[] bytes = verifier.getBytes("US-ASCII");
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(bytes, 0, bytes.length);
byte[] digest = md.digest();
String challenge = Base64.encodeBase64URLSafeString(digest);
Swift 5 サンプル
import CommonCrypto
// ...
guard let data = verifier.data(using: .utf8) else { return nil }
var buffer = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
_ = data.withUnsafeBytes {
CC_SHA256($0.baseAddress, CC_LONG(data.count), &buffer)
}
let hash = Data(buffer)
let challenge = hash.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
// 依存関係: Apple Common Cryptoライブラリ
// http://opensource.apple.com//source/CommonCrypto
u_int8_t buffer[CC_SHA256_DIGEST_LENGTH * sizeof(u_int8_t)];
memset(buffer, 0x0, CC_SHA256_DIGEST_LENGTH);
NSData *data = [verifier dataUsingEncoding:NSUTF8StringEncoding];
CC_SHA256([data bytes], (CC_LONG)[data length], buffer);
NSData *hash = [NSData dataWithBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
NSString *challenge = [[[[hash base64EncodedStringWithOptions:0]
stringByReplacingOccurrencesOfString:@"+" withString:@"-"]
stringByReplacingOccurrencesOfString:@"/" withString:@"_"]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];
ユーザーに認可を求め、authorization_code を付けてアプリへリダイレクトして戻します。
code_verifier と code_challenge を作成したら、次にユーザーの認可を取得する必要があります。これは技術的には の開始にあたり、このステップには次のプロセスのうち 1 つ以上が含まれる場合があります。
- ユーザーを認証する。
- 認証を処理するため、ユーザーを にリダイレクトする。
- アクティブな シングルサインオン (SSO) セッションを確認する。
- 以前に同意が得られていない場合は、要求された権限レベルに対するユーザーの同意を取得する。
ユーザーを認可するには、アプリからユーザーを 認可 URL に送る必要があります。その際、前の手順で生成した code_challenge と、code_challenge の生成に使用したメソッドを含めます。
| Parameter Name | Description |
|---|
response_type | Auth0 が返す認証情報の種類 (code または token) を示します。このフローでは、値は code である必要があります。 |
code_challenge | code_verifier から生成されたチャレンジです。 |
code_challenge_method | チャレンジの生成に使用する方式 (例: S256) です。PKCE 仕様では S256 と plain の 2 つの方式が定義されています。この例では前者を使用しており、後者は非推奨であるため、Auth0 がサポートしているのは 前者のみ です。 |
client_id | アプリケーションのクライアントIDです。この値は Application Settings で確認できます。 |
redirect_uri | ユーザーが認可を付与した後に、Auth0 がブラウザーをリダイレクトする URL です。認可コードは code URL パラメーターで取得できます。この URL は、Application Settings で有効なコールバックURLとして指定する必要があります。
警告: OAuth 2.0 Specification に従い、Auth0 はハッシュ以降をすべて削除し、フラグメントは 一切 考慮しません。 |
scope | 認可をリクエストする スコープ を指定します。これは、どのクレーム (またはユーザー属性) を返すかを決定します。各値はスペースで区切る必要があります。レスポンスで IDトークン を取得するには、少なくとも openid スコープを指定する必要があります。ユーザーの完全なユーザープロファイルを返したい場合は、openid profile をリクエストできます。email などの 標準 OpenID Connect (OIDC) スコープ や、名前空間付き形式 に準拠した カスタムクレーム をリクエストできます。リフレッシュトークン を取得するには offline_access を含めてください (Application Settings で Allow Offline Access フィールドが有効になっていることを確認してください) 。 |
state | (推奨) アプリが初期リクエストに追加し、アプリケーションにリダイレクトするときに Auth0 が含める、不透明な任意の英数字文字列です。この値を使用して Cross-site Request Forgery (CSRF) 攻撃を防ぐ方法については、Mitigate CSRF Attacks With State Parameters を参照してください。 |
connection | (省略可) ユーザーに特定の接続を使ってサインインさせます。たとえば、github という値を渡すと、ユーザーは GitHub アカウントでログインするために直接 GitHub にリダイレクトされます。指定しない場合、ユーザーには設定済みのすべての接続を含む Auth0 Lock 画面が表示されます。設定済みの接続の一覧は、アプリケーションの Connections タブで確認できます。 |
organization | (省略可) ユーザーの認証時に使用する組織の ID です。指定しない場合、アプリケーションで Display Organization Prompt が有効になっていれば、ユーザーは認証時に組織名を入力できます。 |
invitation | (省略可) 組織招待のチケットIDです。組織にメンバーを招待する 場合、ユーザーが招待を承諾したときに、アプリケーションは invitation と organization のキーと値のペアを渡して、招待承諾を処理する必要があります。 |
例として、アプリにログインを追加する際の認可 URL 用 HTML スニペットは次のようになります。
正常に処理されると、HTTP 302 レスポンスが返されます。認可コードは URL の末尾に含まれます。
HTTP/1.1 302 Found
Location: {yourCallbackUrl}?code={authorizationCode}&state=xyzABC123
authorization_code と code_verifier をトークンに交換します。
認可コードを取得したら、それをトークンに交換する必要があります。前の手順で取得した認可コード (code) を使用して、code_verifier とともに トークンURL に POST リクエストを送信します。
| パラメーター名 | 説明 |
|---|
grant_type | "authorization_code" に設定します。 |
code_verifier | このチュートリアルの最初の手順で生成した、暗号学的にランダムなキーです。 |
code | このチュートリアルの前の手順で取得した authorization_code です。 |
client_id | アプリケーションのクライアントIDです。この値は Application Settings で確認できます。 |
redirect_uri | Application Settings で設定した有効なコールバックURLです。これは、このチュートリアルの前の手順で認可 URL に渡した redirect_uri と完全に一致している必要があります。なお、URL エンコードが必要です。 |
正常に処理されると、access_token、refresh_token、id_token、および token_type の各値を含むペイロードを伴う HTTP 200 レスポンスを受け取ります。
{
"access_token":"eyJz93a...k4laUWw",
"refresh_token":"GEbRxBN...edjnXbL",
"id_token":"eyJ0XAi...4faeEoQ",
"token_type":"Bearer",
"expires_in":86400
}
IDトークンには、デコードして取り出す必要があるユーザー情報が含まれています。
アクセストークンは、Auth0 Authentication API の /userinfo エンドポイントまたは別の API を呼び出すために使用します。独自の API を呼び出す場合、API で最初に行う必要があるのは、アクセストークンを検証することです。
リフレッシュトークンは、以前のアクセストークンまたは IDトークン の有効期限が切れた後に、新しいアクセストークンまたは IDトークン を取得するために使用されます。refresh_token がレスポンスに含まれるのは、offline_access スコープを指定し、Dashboard で API に対して Allow Offline Access を有効にした場合のみです。
リフレッシュトークンを使うと、ユーザーの認証状態を実質的に無期限で維持できるため、安全に保存する必要があります。
この例は、手順 1 でユーザーを認証する際に送信できる最も基本的なリクエストを示しています。Auth0 のログイン画面が表示され、ユーザーは設定済みの任意の接続でサインインできます。
ここでトークンをリクエストすると、IDトークンには最も基本的なクレームが含まれます。IDトークンをデコードすると、次のようになります。
{
"iss": "https://auth0pnp.auth0.com/",
"sub": "auth0|581...",
"aud": "xvt9...",
"exp": 1478112929,
"iat": 1478076929
}
通常の認証に加えて、この例では、名前やプロフィール画像などの追加のユーザー情報をリクエストする方法を示します。
ユーザーの名前とプロフィール画像をリクエストするには、ユーザーの認可時に適切なスコープを追加する必要があります。
これで、トークンをリクエストすると、IDトークンに要求したnameおよびpictureクレームが含まれるようになります。IDトークンをデコードすると、次のようになります。
{
"name": "auth0user@...",
"picture": "https://example.com/profile-pic.png",
"iss": "https://auth0user.auth0.com/",
"sub": "auth0|581...",
"aud": "xvt...",
"exp": 1478113129,
"iat": 1478077129
}
通常のユーザー認証に加え、この例では GitHub などのソーシャル IDプロバイダーにユーザーを直接リダイレクトする方法を示します。この例を動作させるには、Auth0 Dashboard > Authentication > Social に移動し、適切な接続を設定する必要があります。接続名は Settings タブで確認します。
ユーザーを GitHub のログイン画面に直接リダイレクトするには、ユーザーを認可する際に connection パラメーターを渡し、その値を接続名 (この場合は github) に設定する必要があります。
トークンをリクエストすると、IDトークンには GitHub から返されたユーザーの一意の ID を含む sub クレームが含まれます。IDトークンをデコードすると、次のような内容になります。
{
"name": "John Smith",
"picture": "https://avatars.example.com",
"email": "jsmith@...",
"email_verified": true,
"iss": "https://auth0user.auth0.com/",
"sub": "github|100...",
"aud": "xvt...",
"exp": 1478114742,
"iat": 1478078742
}