Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebAuthnError(reason: PassDemo.WebAuthnError.Reason.invalidAttestationObject) #67

Open
jaydipdeveloper opened this issue May 7, 2024 · 5 comments

Comments

@jaydipdeveloper
Copy link

import UIKit
import CryptoKit
import SafariServices
import AuthenticationServices

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    
    let webAuthnManager = WebAuthnManager(
        configuration: WebAuthnManager.Configuration(
            relyingPartyID: "domain.ai",
            relyingPartyName: "My Fancy Web App",
            relyingPartyOrigin: "https://domain.ai"
        )
    )
    
    Task {
        let result = webAuthnManager.beginRegistration(user: PublicKeyCredentialUserEntity(id: self.generateRandomBytes(count: 10), name: "Jaydip", displayName: "Jaydip Finava"))
        print(result)
        
        let id = result.user.id.base64URLEncodedString()
        let data = generateClientDataJSON(challenge:  Data(result.challenge)

, origin: "https://domia.ai", type: "webauthn.create", tokenBinding: nil)
print(data!)

        let byteArray: [UInt8] = Array(data!)
        
        
        let newData = generateDataJSON()!
        let byteArray1: [UInt8] = Array(newData)
        
        let request = RegistrationCredential(id: id, type: .publicKey, rawID: result.challenge, attestationResponse: AuthenticatorAttestationResponse(clientDataJSON: byteArray, attestationObject: byteArray1))
        
        //RegistrationCredential(id: id, type: CredentialType.publicKey, rawID: result.user.id, attestationResponse: AuthenticatorAttestationResponse(clientDataJSON: [UInt8].random(count: 32), attestationObject: [UInt8].random(count: 32)))
        
       
        
        
        let confirmCredentialIDNotRegisteredYet: (String) async throws -> Bool = { credentialID in
            return true
        }
        do {
            let credential = try await webAuthnManager.finishRegistration(
                challenge: result.challenge,
                credentialCreationData: request,
                confirmCredentialIDNotRegisteredYet: confirmCredentialIDNotRegisteredYet
            )
            print(credential)
        } catch {
            print(error)
        }
    }
    
}

func generateRandomBytes(count: Int) -> [UInt8] {
    var randomBytes = [UInt8]()
    for _ in 0..<count {
        let randomByte = UInt8(arc4random_uniform(UInt32(UInt8.max)))
        randomBytes.append(randomByte)
    }
    return randomBytes
}
       
func generateClientDataJSON(challenge: Data, origin: String, type: String, tokenBinding: String?) -> Data? {
    var clientData: [String: Any] = [
        "challenge": challenge.base64EncodedString(),
        "origin": origin,
        "type": type
    ]
    if let tokenBinding = tokenBinding {
        clientData["tokenBinding"] = tokenBinding
    }
    do {
        let jsonData = try JSONSerialization.data(withJSONObject: clientData)
        return jsonData
    } catch {
        print("Error serializing client data JSON: \(error)")
        return nil
    }
}


func generateDataJSON() -> Data? {
    let clientData: [String: Any] = [
        "rpIdHash": sha256("domain.ai"),
        "signCount": 0
    ]
    do {
        let jsonData = try JSONSerialization.data(withJSONObject: clientData)
        return jsonData
    } catch {
        print("Error serializing client data JSON: \(error)")
        return nil
    }
}

func sha256(_ input: String) -> String {
    // Convert the input string to data using UTF-8 encoding
    guard let inputData = input.data(using: .utf8) else {
        return ""
    }
    let hashedData = SHA256.hash(data: inputData)
    
    // Convert the hash to a hexadecimal string
    let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined()
    
    return hashString
}

}

@0xTim
Copy link
Member

0xTim commented May 7, 2024

I recommend reading up on how Passkeys work on iOS and how you should be implementing them. You should not be using webAuthnManager on iOS - that lives on your server. The iOS app is the client and should use ASAuthenticationServices

@jaydipdeveloper
Copy link
Author

I have password manager app and I want to passkey for webauthn.io from my Auto fill extension is that possible? how can you give me sample code?

@jaydipdeveloper
Copy link
Author

Begin registration works well here are the response of that method

PublicKeyCredentialCreationOptions(challenge: [175, 165, 121, 16, 203, 47, 228, 14, 38, 138, 152, 97, 202, 28, 17, 133, 103, 17, 53, 230, 251, 107, 245, 65, 161, 206, 227, 55, 1, 86, 239, 255], user: PassDemo.PublicKeyCredentialUserEntity(id: [71, 93, 209, 225, 177, 115, 193, 76, 130, 123], name: "Jaydip", displayName: "Jaydip Finava"), relyingParty: PassDemo.PublicKeyCredentialRelyingPartyEntity(id: "oloid.ai", name: "My Fancy Web App"), publicKeyCredentialParameters: [PassDemo.PublicKeyCredentialParameters(type: PassDemo.CredentialType(rawValue: "public-key"), alg: PassDemo.COSEAlgorithmIdentifier.algES256), PassDemo.PublicKeyCredentialParameters(type: PassDemo.CredentialType(rawValue: "public-key"), alg: PassDemo.COSEAlgorithmIdentifier.algES384), PassDemo.PublicKeyCredentialParameters(type: PassDemo.CredentialType(rawValue: "public-key"), alg: PassDemo.COSEAlgorithmIdentifier.algES512)], timeout: Optional(3600.0 seconds), attestation: PassDemo.AttestationConveyancePreference.none)

@0xTim
Copy link
Member

0xTim commented May 9, 2024

You cannot run it on the client - it is insecure and must be run on the server to verify the attestations

@jaydipdeveloper
Copy link
Author

jaydipdeveloper commented May 9, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants