Skip to content

Commit

Permalink
Merge pull request #1 from octopus-energy/142hitesh/fix-invalid-code-…
Browse files Browse the repository at this point in the history
…verifier

Fixing invalid code verifier issue for auth flow
  • Loading branch information
142hitesh authored Feb 17, 2023
2 parents 37b9a52 + 3aca33d commit 34e8d8b
Showing 1 changed file with 47 additions and 3 deletions.
50 changes: 47 additions & 3 deletions Sources/TeslaSwift/Model/Authentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class AuthTokenRequestWeb: Encodable {

init(grantType: GrantType = .authorizationCode, code: String? = nil, refreshToken: String? = nil) {
if grantType == .authorizationCode {
codeVerifier = oAuthClientID.codeVerifier
codeVerifier = CodeChallengeHelper.verifier
self.code = code
redirectURI = oAuthRedirectURI
} else if grantType == .refreshToken {
Expand Down Expand Up @@ -148,12 +148,12 @@ class AuthCodeRequest: Encodable {
var clientSecret = oAuthClientSecret
var redirectURI = oAuthRedirectURI
var scope = oAuthScope
let codeChallenge: String
let codeChallenge: String?
var codeChallengeMethod = "S256"
var state = "teslaSwift"

init() {
self.codeChallenge = clientID.codeVerifier.challenge
self.codeChallenge = CodeChallengeHelper.challange
}

// MARK: Codable protocol
Expand Down Expand Up @@ -182,6 +182,50 @@ class AuthCodeRequest: Encodable {
}
}

// MARK: - PKCE Code Verifier & Code Challenge

enum PKCEError: Error {
case failedToGenerateRandomOctets
case failedToCreateChallengeForVerifier
}

struct CodeChallengeHelper {
static let verifier = try? base64URLEncode(octets: generateCryptographicallySecureRandomOctets(count: 64))

static let challange: String? = {
guard let verifier = verifier else {
return nil
}

let challenge = verifier
.data(using: .ascii)
.map { SHA256.hash(data: $0) }
.map { base64URLEncode(octets: $0) }

return challenge
}()

private static func generateCryptographicallySecureRandomOctets(count: Int) throws -> [UInt8] {
var octets = [UInt8](repeating: 0, count: count)
let status = SecRandomCopyBytes(kSecRandomDefault, octets.count, &octets)
if status == errSecSuccess {
return octets
} else {
throw PKCEError.failedToGenerateRandomOctets
}
}

private static func base64URLEncode<S>(octets: S) -> String where S: Sequence, UInt8 == S.Element {
let data = Data(octets)
return data
.base64EncodedString()
.replacingOccurrences(of: "=", with: "")
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.trimmingCharacters(in: .whitespaces)
}
}

extension String {
var codeVerifier: String {
let verifier = self.data(using: .utf8)!.base64EncodedString()
Expand Down

0 comments on commit 34e8d8b

Please sign in to comment.