Skip to content

Commit

Permalink
Merge pull request OAuthSwift#647 from MrWoWander/pkce
Browse files Browse the repository at this point in the history
Code verifier & code challenge generator for working with PKCE
  • Loading branch information
phimage authored Apr 29, 2021
2 parents ab08d91 + 36a90e4 commit efda1f3
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 3 deletions.
5 changes: 5 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ let package = Package(
.testTarget(name: "OAuthSwiftTests", dependencies: ["OAuthSwift", "Erik", "Kanna", "Swifter"], path: "OAuthSwiftTests"),
]
)

#if os(Linux)
package.dependencies.append(.package(url: "https://github.com/apple/swift-crypto.git", from: "1.0.0"))
package.targets[0].dependencies.append("Crypto")
#endif
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ oauthswift = OAuth2Swift(
)
oauthswift.accessTokenBasicAuthentification = true

let codeVerifier = base64url("abcd...")
let codeChallenge = codeChallenge(for: codeVerifier)
guard let codeVerifier = generateCodeVerifier() else {return}
guard let codeChallenge = generateCodeChallenge(codeVerifier: codeVerifier) else {return}

let handle = oauthswift.authorize(
withCallbackURL: "myApp://callback/",
Expand All @@ -210,7 +210,6 @@ let handle = oauthswift.authorize(

```


See demo for more examples

### Handle authorize URL
Expand Down
44 changes: 44 additions & 0 deletions Sources/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

import Foundation

#if os(Linux)
import Crypto
#else
import CommonCrypto
#endif

public func generateState(withLength len: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let length = UInt32(letters.count)
Expand All @@ -21,3 +27,41 @@ public func generateState(withLength len: Int) -> String {
}
return randomString
}

/// Generating a code verifier for PKCE
public func generateCodeVerifier() -> String? {
var buffer = [UInt8](repeating: 0, count: 32)
_ = SecRandomCopyBytes(kSecRandomDefault, buffer.count, &buffer)
let codeVerifier = Data(buffer).base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
.trimmingCharacters(in: .whitespaces)

return codeVerifier
}

/// Generating a code challenge for PKCE
public func generateCodeChallenge(codeVerifier: String?) -> String? {
guard let verifier = codeVerifier, let data = verifier.data(using: .utf8) else { return nil }

#if !os(Linux)
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)
#else
let buffer = [UInt8](repeating: 0, count: SHA256.byteCount)
let sha = Array(HMAC<SHA256>.authenticationCode(for: buffer, using: SymmetricKey(size: .bits256)))
let hash = Data(sha)
#endif

let challenge = hash.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
.trimmingCharacters(in: .whitespaces)

return challenge
}

0 comments on commit efda1f3

Please sign in to comment.