0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OAuth2.0の「PKCEデータ」ってなに?

Posted at

PKCE (Proof Key for Code Exchange) extension to OAuth 2.0

図で分かりやすいと思います。

簡単な説明

クライアント側であらかじめcode_verifiercode_challengeを作っておく。
OAuth2.0の認証API(/authorize)にcode_challengeを与える。
トークン交換API(/token)でcode_verifierを与える。
そうすると、認証サーバー側で 検証できて不正検知できる。

code_verifierの作成

code_verifierはhigh-entropy cryptographic stringであることが期待。要は、セキュアな乱数関数を使って32bytesの長さのものを作ればよい。以下はおもちゃ的な実装だがイメージしやすい。

Swift実装

func generateCodeVerifier() -> String {
    let length = 32
    var randomBytes = [UInt8](repeating: 0, count: length)
    let result = SecRandomCopyBytes(kSecRandomDefault, length, &randomBytes)
    if result != errSecSuccess {
        fatalError("生成できまちぇんでちた")
    }
    let codeVerifier = Data(randomBytes).base64EncodedString()
    return codeVerifier
}

code_challengeの作成

code_verifierから生成する。code_verifierをそのもの出してもいいらしいけどセキュリティ的に弱くなってしまうので、SHA256で生成するのは一般的。/authorize APIでcode_challenge_method=S256渡したしね。

Swift実装

import Foundation
import CommonCrypto

func generateCodeChallenge(from codeVerifier: String) -> String? {
    guard let data = codeVerifier.data(using: .utf8) else { return nil }
    var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
    data.withUnsafeBytes {
        _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash)
    }
    return Data(hash).base64EncodedString()
}

上記のシーケンス図

PlantUMLないとね

@startuml
actor User
participant "Client\nApp" as NativeClient
participant "WebView" as WebView
participant "Authorization\nServer" as AuthServer
participant "Resource\nServer" as ResourceServer

NativeClient -> NativeClient: Generate\n<font color=red>code_verifier=Random 32 bytes</font> and\n<font color=red>code_challenge=SHA256(code_verifier)</font>
NativeClient -> WebView++: Open WebView\nand pass challenge
WebView -> AuthServer: Authorization Request\n(GET /authorize?response_type=code&client_id=...&<font color=red>code_challenge=...&code_challenge_method=S256</font>&<font color=magenta>redirect_uri</font>=...)
AuthServer -> AuthServer: Store <font color=red>code_challenge</font> and\n<font color=red>code_challenge_method</font>
AuthServer --> WebView: 302 redirect to login form page
WebView --> User: Show login form
User -> WebView: Enter credentials\nand submit
WebView -> AuthServer: Send credentials
AuthServer --> WebView: Display consent screen
WebView --> User: Show consend screen
User -> WebView: Approve consent
WebView -> AuthServer: Approve consent
AuthServer -> WebView: Redirect to <font color=magenta>redirect_uri</font>\nwith authorization <font color=blue>code</font> (302 Redirect)
WebView -> NativeClient: Provide authorization <font color=blue>code</font>
deactivate WebView
NativeClient -> AuthServer: Access Token Request\n(POST /token with <font color=blue>code</font>, <font color=red>code_verifier</font>, <font color=magenta>redirect_uri</font>, ...)
AuthServer -> AuthServer: Verify <font color=red>code_verifier</font>\nmatches <font color=red>code_challenge</font>
AuthServer --> NativeClient: Access Token Response\n(including <b>access_token</b>, token_type, expires_in, refresh_token)
NativeClient -> ResourceServer: Request Resource\n(with <b>access_token</b>)
ResourceServer --> NativeClient: Resource Response
@enduml

以上です。

役にたつといいですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?