This is a WAI middleware which introduces a simple authentication mechanism based on Web Authentication API (WebAuthn).
One easy way to configure the middleware is to use YAML.
import qualified Network.Wai.Middleware.WebAuthn as WebAuthn
import qualified Data.Yaml as Yaml
main = do
config <- Yaml.decodeFileThrow "config.yaml"
mid <- WebAuthn.mkMiddleware config
...
origin: "https://localhost:8080"
endpoint: "webauthn"
authorisedKeys:
fumieval:
credentialId: "0IMo2OFRmM903AGEP5/1u5eVGlcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
publicKey: "pQECAyYgASFYICJwKPYkRYKWH6OIAjp+IDghFnl06S0iSGjxn/arBp0OIlggoJmTH1ZaVWCrn3A2b+wZx4/mVePRFowKujU5xXmafJY="
This middleware exposes a JavaScript library in /lib.js
:
You must import following scripts in order to make it work:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/cbor.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/base64js.min.js"></script>
Here's the pseudo-code describing the content of the library.
CredentialId = String -- Credential Id
CredentialPublicKey = String -- Public key
Credential =
{ credentialId : CredentialId
, publicKey : CredentialPublicKey
}
Token = String -- Token for authorisation
Identifier = String -- Human-readable identifier for a Credential
Endpoint = String -- The prefix of the middleware API e.g. "webauthn"
User = -- Information stored in the authenticator
{ id : String
, name : String
, displayName : String
}
WebAuthnProxy : Endpoint ->
{ register : User -> Promise Credential
-- Register a user to the authenticator and returns a credential if it's valid.
-- Once verified, insert the Credential to the list of authorisedKeys into the configuraion.
, verify : CredentialId -> Promise Token
-- Verify a credential using the public key stored in the server.
-- Returns a token if succeeds.
, lookup : Identifier -> Promise CredentialId
-- Find a CredentialId associated to the Identifier (provisional).
}
Whenever it receives a request containing Authentication: XXX
, it checks if XXX
is a valid token generated by verify
.
It replaces XXX
by the associated identifier which can be extracted by requestIdentifier :: Request -> Maybe Identifier
.