Spotify PKCE yetkilendirme akışı "code_verifier was yanlış" döndürüyor

Aug 19 2020

PKCE kullanarak uygulamamın kimliğini doğrulamak için Spotify API's Authentication Guide'ı takip ediyorum.

Şu an itibariyle, hata ayıklama için önceden hesaplanmış bir meydan okuma ile sahte bir kod doğrulayıcı kullanıyorum . Bu değerler, birden çok çevrimiçi araç ( SHA256 , SHA256 , base64url , base64url ) kullanılarak hesaplandı ve Swift'de yazdığım hashing / kodlama işlevlerinden döndürülen değerlerle eşleşti. Bunları doğrulamak için yukarıdaki bağlantıları kullanmaktan çekinmeyin.

let verifier = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
let challenge = "66d34fba71f8f450f7e45598853e53bfc23bbd129027cbb131a2f4ffd7878cd0"
let challengeBase64URL = "NjZkMzRmYmE3MWY4ZjQ1MGY3ZTQ1NTk4ODUzZTUzYmZjMjNiYmQxMjkwMjdjYmIxMzFhMmY0ZmZkNzg3OGNkMA"

2. adımdaki ilk isteğimi yapmak için ASWebAuthenticationSession kullanıyorum, örneğin:

var components = URLComponents()
components.scheme = "https"
components.host = "accounts.spotify.com"
components.path = "/authorize"
components.queryItems = [
    URLQueryItem(name: "client_id", value: SpotifyClientID),
    URLQueryItem(name: "response_type", value: "code"),
    URLQueryItem(name: "redirect_uri", value: SpotifyRedirectURL.absoluteString),
    URLQueryItem(name: "code_challenge_method", value: "S256"),
    URLQueryItem(name: "code_challenge", value: challenge),
    URLQueryItem(name: "state", value: "testing-state"),
    URLQueryItem(name: "scope", value: "user-follow-read")
]
let urlString = components.url!.absoluteString

guard let authURL = URL(string: urlString) else { return }
print(authURL)
let authSession = ASWebAuthenticationSession(url: authURL, callbackURLScheme: callbackScheme, completionHandler: handleLoginResponse)
authSession.presentationContextProvider = self
authSession.prefersEphemeralWebBrowserSession = true
authSession.start()

İçinde handleLoginResponse, 3. adımdaki yanıtı ayrıştırıyorum ve Alamofire kullanarak 4. adım için ağ talebinde bulunuyorum:

guard let items = URLComponents(string: callbackURL?.absoluteString ?? "").queryItems else { return }
let authCode = items[0].value!
let endpoint = "https://accounts.spotify.com/api/token"

let headers = HTTPHeaders(["Content-Type": "application/x-www-form-urlencoded"])
let parameters: [String: String] = [
    "client_id": SpotifyClientID,
    "grant_type": "authorization_code",
    "code": authCode,
    "redirect_uri": SpotifyRedirectURL.absoluteString,
    "code_verifier": verifier!
]
AF.request(endpoint,
           method: .post,
           parameters: parameters,
           encoder: URLEncodedFormParameterEncoder.default,
           headers: headers
).cURLDescription() { description in
    print(description)
}
.responseJSON() { (json) in
    print(json)
}

Alamofire, Swift içinden cURL istekleri yapmak için bir arayüz oluşturur ve arama cURLDescription(), gerçek cURL komutunun tam olarak ne olduğunu görmemi sağlar:

$ curl -v \
    -X POST \
    -b "__Host-device_id=AQBHyRKdulrPJU6vY5xlua1xKOZBtBZVcrW9IK-X0LQ_MPj5x3N4mZkF4OzgLMdQwviWUxJ2dY6d49d0QpjG0ayFtCfrhwzG5-g" \
    -H "User-Agent: SpotifyUserGraph/1.0 (hl999.SpotifyUserGraph; build:1; iOS 14.0.0) Alamofire/5.1.0" \
    -H "Accept-Encoding: br;q=1.0, gzip;q=0.9, deflate;q=0.8" \
    -H "Accept-Language: en-US;q=1.0, zh-Hans-US;q=0.9, ko-US;q=0.8" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "client_id=e11fb810282946569aab8f89e52f78d5&code=AQC3Lm3KDPFCg3mBjSAiXMyvjdn5GvUJCjjCTQzPhAFe5mLntAHcAeiEufXcCv3Jne2qn345MZxBNiCggO-35mn6AAFsjRlm5lPynyC6clWABSzBK1OdWIynTlf0CiyR8vWYeO54GHHEXBSzj6URKWnAiXuxTUV6n1Axra6Oet8FY6-0jwU0CNGMaB91q1JFXlyl5J9JvrRtrP3s2Ef8Xb5A7gcCzqW6RHRzO0--BKiPHFnprK0SitiLxi-md2aaMnS2aHsRTqvc_NfFcuRpFR05WmSm6Gvkk_9trSBqRvVZYuGs-Ap3-ydVGk7BCqNc3lpbh4Jku6W_930fOg9kI__zRA&code_verifier=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&grant_type=authorization_code&redirect_uri=hl999-spotifyusergraph%3A//spotify-login-callback" \
    "https://accounts.spotify.com/api/token"

Okuması biraz zor, ancak isteğin doğru yapıldığından oldukça eminim.

Ancak, 4. adımda, bu hata iletisini her zaman sunucudan alıyorum:

error = "invalid_grant";
"error_description" = "code_verifier was incorrect";

Birkaç saat boyunca birçok şeyi denedim ve hala çözemiyorum. Herhangi bir işaret çok takdir edilecektir. Teşekkürler!

Yanıtlar

2 Sn0w0dDev Sep 17 2020 at 01:55

Sizin sorununuz, SHA hash'in ham baytlarının base64 olması gereken şey olmasıdır. Ayrıca Alamofire ve Spotify PKCE kullanan ve kod sorunuyla ilgili sorun yaşayan bir uygulama üzerinde çalışıyorum. Yaptığım şey, Swift 3 için yazılmış olan ve Swift 5 ile çalışacak şekilde değiştirilen Auth0 belgelerinden bazı kodları kullanmaktı :

import Foundation
import CommonCrypto
 
func challenge(verifier: String) -> String {
    
    guard let verifierData = verifier.data(using: String.Encoding.utf8) else { return "error" }
        var buffer = [UInt8](repeating: 0, count:Int(CC_SHA256_DIGEST_LENGTH))
 
        verifierData.withUnsafeBytes {
            CC_SHA256($0.baseAddress, CC_LONG(verifierData.count), &buffer)
        }
    let hash = Data(_: buffer)
    print(hash)
    let challenge = hash.base64EncodedData()
    return String(decoding: challenge, as: UTF8.self)
        .replacingOccurrences(of: "+", with: "-")
        .replacingOccurrences(of: "/", with: "_")
        .replacingOccurrences(of: "=", with: "")
        .trimmingCharacters(in: .whitespaces)
}
print(challenge(verifier: "ExampleVerifier"))

Umarım bu yardımcı olur ve size iyi şanslar!

GaryArcher Aug 19 2020 at 18:27

Bu çevrimiçi PKCE doğrulayıcısını kullandığımda , doğrulayıcı için farklı bir zorlukla karşılaştım, bu yüzden belki aracın size verdiği değerlerle yeniden deneyebilirim.

GENEL GÜVENLİK

Güvenliği kendiniz kodlamanıza gerek kalmaması için AppAuth gibi saygın bir güvenlik kitaplığı kullanırdım. Kitaplıklar olası hatalardan kaçınmamıza yardımcı olur ve gelecekte ücretsiz olarak yeni güvenlik özellikleri alırız.

APPAUTH ENTEGRASYONU

Bu yaklaşımla ilgileniyorsanız, bu adımlar ve kaynaklarım yararlı olabilir:

  • AppAuth Örneğini Çalıştırma
  • Ardından, Spotify ile çalıştığından emin olmak için yapılandırmanızı güncelleyin
  • Gelişmiş AppAuth Örneği , yaygın mobil OAuth sorunlarını aşmak için daha ayrıntılı bazı alanları kapsar

KOD

İşte kütüphaneleri entegre eden bazı Swift kodum var ve düşük seviyeli PKCE işlemeye gerek yok.