Keine Beschreibung

Lukas Angerer 3f043dbc0a Configurable host for demo deployment on larcanum.net vor 2 Jahren
Properties 3f043dbc0a Configurable host for demo deployment on larcanum.net vor 2 Jahren
data 3f043dbc0a Configurable host for demo deployment on larcanum.net vor 2 Jahren
requests 69b1c499d1 Building credentials create options vor 2 Jahren
wwwroot b562a65cc5 Improved token mapping and added debug information to protected result vor 2 Jahren
.gitignore fe9fba8e8d Initial commit vor 2 Jahren
Base64UrlConverter.cs fa10fcb7fa Saving credentials on the server vor 2 Jahren
CredentialManager.cs 3f043dbc0a Configurable host for demo deployment on larcanum.net vor 2 Jahren
Folder.DotSettings 69b1c499d1 Building credentials create options vor 2 Jahren
JwtConfig.cs 3f043dbc0a Configurable host for demo deployment on larcanum.net vor 2 Jahren
NameTransform.cs 69b1c499d1 Building credentials create options vor 2 Jahren
OptionsCache.cs dd1bb1609f Server side credential verification vor 2 Jahren
OptionsWithName.cs dd1bb1609f Server side credential verification vor 2 Jahren
Passwordless.csproj 1789ae4b68 Creating a JWT with a custom demo JWK vor 2 Jahren
Passwordless.http fe9fba8e8d Initial commit vor 2 Jahren
Program.cs 3f043dbc0a Configurable host for demo deployment on larcanum.net vor 2 Jahren
README.md c0c9a197e4 Documentation vor 2 Jahren
appsettings.Development.json fe9fba8e8d Initial commit vor 2 Jahren
appsettings.json fe9fba8e8d Initial commit vor 2 Jahren
demo-jwk.json 1789ae4b68 Creating a JWT with a custom demo JWK vor 2 Jahren

README.md

This is a very basic demo of passwordless authentication in the web, also known as "WebAuthn".

Overview

Technical Details

Note that for convenience, the client always sends the base64URL encoded user name from the UI to the server. This encoded version is used as the Fido2User.Id while the decoded version is stored as the Fido2User.DisplayName and the Fido2User.Name is then derived from the display name by converting all characters to lower case and replacing "offending" file name characters with "_".

Registration

Building a Challange for Creating a new Credential

CredentialCreateOptions generated by the program looks like this:

  • The algorithm identifiers are defined in the IANA registry
  • The create options have to be post-processed on the client before they can be used with navigator.credentials.create by converting base64URL encoded strings to byte arrays (Uint8Array)

    {
    "rp": {
    "id": "localhost",
    "name": "FIDO2 Test"
    },
    "user": {
    "name": "test osteron",
    "id": "VGVzdCBPc3Rlcm9u",
    "displayName": "Test Osteron"
    },
    "challenge": "UkTN1q5kjoWcHOFTB6AZWQ",
    "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    },
    {
      "type": "public-key",
      "alg": -257
    },
    {
      "type": "public-key",
      "alg": -37
    },
    {
      "type": "public-key",
      "alg": -35
    },
    {
      "type": "public-key",
      "alg": -258
    },
    {
      "type": "public-key",
      "alg": -38
    },
    {
      "type": "public-key",
      "alg": -36
    },
    {
      "type": "public-key",
      "alg": -259
    },
    {
      "type": "public-key",
      "alg": -39
    },
    {
      "type": "public-key",
      "alg": -8
    }
    ],
    "timeout": 60000,
    "attestation": "none",
    "authenticatorSelection": {
    "requireResidentKey": false,
    "userVerification": "discouraged"
    },
    "excludeCredentials": [],
    "extensions": {
    "exts": true,
    "uvm": false
    },
    "status": "ok",
    "errorMessage": ""
    }
    

Creating the Credential

The result of calling navigator.credentials.create with the options & challange from the server is an object that mostly contains binary data:

  • id and rawId fields represent the same Credential ID, the raw version is an array buffer while the "plain" version is a base64URL encoded representation. The (plain / non-raw) ID of the credential looks like: BKbtxxiJoPWfT8x_3fUwlzXYIR6OwRXSQGH-FMykKcthocRhAznj8DMNY-2YZw7By-HNnEJa1CxjTPK0WyzjwQ
  • authenticatorAttachment declares what type of authenticator provided the credential ("cross-platform" meaning a roaming authenticator)
  • type being the type of the credential that was generated (generally "public-key")
  • response.attestationObject is a CBOR encoded ArrayBuffer which contains the authenticator data and attestation (if present)
  • response.clientDataJSON contains some... client data including the challenge value that was used and the RP origin

    {
        "type": "webauthn.create",
        "challenge": "NwZKS4GobKzOqa5YvPPD2g",
        "origin": "http://localhost:5172",
        "crossOrigin": false
    }
    

Storing the Credentials

We again need to do some reformatting, this time from byte arrays to base64URL encoded strings and then the data from the authenticator is directly sent to the server for verification.

{
    "id": "BKbtxxiJoPWfT8x_3fUwlzXYIR6OwRXSQGH-FMykKcthocRhAznj8DMNY-2YZw7By-HNnEJa1CxjTPK0WyzjwQ",
    "rawId": "BKbtxxiJoPWfT8x/3fUwlzXYIR6OwRXSQGH+FMykKcthocRhAznj8DMNY+2YZw7By+HNnEJa1CxjTPK0WyzjwQ==",
    "type": "public-key",
    "extensions": {},
    "response": {
        "AttestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjESZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2NFAAAABAAAAAAAAAAAAAAAAAAAAAAAQASm7ccYiaD1n0/Mf931MJc12CEejsEV0kBh/hTMpCnLYaHEYQM54/AzDWPtmGcOwcvhzZxCWtQsY0zytFss48GlAQIDJiABIVggrEeUH2MVMs5oI0dZOGu9Sm9w/5iMFMRXczBtsDrmSOgiWCBO1F75pFRnZS6wRC3LIvt2U7C10i0gQd73NRG3A38bZA==",
        "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiTndaS1M0R29iS3pPcWE1WXZQUEQyZyIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTE3MiIsImNyb3NzT3JpZ2luIjpmYWxzZX0=",
        "transports": []
    }
}

The server has to compare this response with the challenge from the creation options (the creation options are cached on the server or persisted in the session). Once successful, the credential is persisted in a file "[username].json".

Login

Stored Data

Currently, we directly store the AttestationVerificationSuccess that the client sends to complete the registration process.

my username.json