Skip to content

Commit

Permalink
Make code sort of work with some base64 URL decoding.
Browse files Browse the repository at this point in the history
  • Loading branch information
jeroenleenarts committed Jun 14, 2022
1 parent ace7a7d commit b385078
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 20 deletions.
6 changes: 3 additions & 3 deletions Sources/App/routes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func routes(_ app: Application) throws {
let user = User(id: userID, username: username)
try await user.save(on: req.db)

let credential = WebAuthnCredential(id: credential.credentialID, publicKey: credential.publicKey.pemRepresentation, userID: userID)
try await credential.save(on: req.db)
let webAuthnCredential = WebAuthnCredential(id: credential.credentialID, publicKey: credential.publicKey.pemRepresentation, userID: userID)
try await webAuthnCredential.save(on: req.db)

req.auth.login(user)

Expand All @@ -76,7 +76,7 @@ func routes(_ app: Application) throws {
req.logger.debug("Authenticate Challenge is \(encodedChallenge)")
req.session.data["challenge"] = encodedChallenge
req.session.data["userID"] = try user.requireID().uuidString
let credentials = try await user.$credentials.get(on: req.db).map {
let credentials: [WebAuthnCredential] = try await user.$credentials.get(on: req.db).map {
// We need to convert the IDs to base64 encoded from base64 URL encoded
var id = $0.id!.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
while id.count % 4 != 0 {
Expand Down
33 changes: 16 additions & 17 deletions Sources/WebAuthn/WebAuthn.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@ import Crypto
import Logging
import Foundation

extension String {
var base64URLDecodedData: Data? {
var result = self.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
while result.count % 4 != 0 {
result = result.appending("=")
}
return Data(base64Encoded: result)
}
}

public enum WebAuthn {
public static func validateAssertion(_ data: AssertionCredential, challengeProvided: String, publicKey: P256.Signing.PublicKey, logger: Logger) throws {
guard let clientObjectData = Data(base64Encoded: data.response.clientDataJSON) else {
guard let clientObjectData = data.response.clientDataJSON.base64URLDecodedData else {
throw WebAuthnError.badRequestData
}
let clientObject = try JSONDecoder().decode(ClientDataObject.self, from: clientObjectData)
Expand All @@ -14,20 +24,12 @@ public enum WebAuthn {
}
let clientDataJSONHash = SHA256.hash(data: clientObjectData)

var base64AssertionString = data.response.authenticatorData.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
while base64AssertionString.count % 4 != 0 {
base64AssertionString = base64AssertionString.appending("=")
}
guard let authenticatorData = Data(base64Encoded: base64AssertionString) else {
guard let authenticatorData = data.response.authenticatorData.base64URLDecodedData else {
throw WebAuthnError.badRequestData
}
let signedData = authenticatorData + clientDataJSONHash

var base64SignatureString = data.response.signature.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
while base64SignatureString.count % 4 != 0 {
base64SignatureString = base64SignatureString.appending("=")
}
guard let signatureData = Data(base64Encoded: base64SignatureString) else {
guard let signatureData = data.response.signature.base64URLDecodedData else {
throw WebAuthnError.badRequestData
}
let signature = try P256.Signing.ECDSASignature(derRepresentation: signatureData)
Expand All @@ -37,7 +39,7 @@ public enum WebAuthn {
}

public static func parseRegisterCredentials(_ data: RegisterWebAuthnCredentialData, challengeProvided: String, origin: String, logger: Logger) throws -> Credential {
guard let clientObjectData = Data(base64Encoded: data.response.clientDataJSON) else {
guard let clientObjectData = data.response.clientDataJSON.base64URLDecodedData else {
throw WebAuthnError.badRequestData
}
let clientObject = try JSONDecoder().decode(ClientDataObject.self, from: clientObjectData)
Expand All @@ -50,11 +52,8 @@ public enum WebAuthn {
guard origin == clientObject.origin else {
throw WebAuthnError.validationError
}
var base64AttestationString = data.response.attestationObject.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
while base64AttestationString.count % 4 != 0 {
base64AttestationString = base64AttestationString.appending("=")
}
guard let attestationData = Data(base64Encoded: base64AttestationString) else {

guard let attestationData = data.response.attestationObject.base64URLDecodedData else {
throw WebAuthnError.badRequestData
}
guard let decodedAttestationObject = try CBOR.decode([UInt8](attestationData)) else {
Expand Down

0 comments on commit b385078

Please sign in to comment.