Skip to content

Commit

Permalink
Merge pull request #42 from lstoll/lstoll-new-webauthn
Browse files Browse the repository at this point in the history
Use library discoverable login
  • Loading branch information
lstoll authored Mar 9, 2024
2 parents 63d37df + a854893 commit 69d0412
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 31 deletions.
6 changes: 6 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
"clientID": "client-id",
"clientSecrets": ["client-secret"],
"redirectURLs": ["http://localhost:8084/callback"]
},
{
"clientID": "cli",
"clientSecrets": ["secret"],
"public": true,
"redirectURLs": ["http://localhost"]
}
]
}
Expand Down
19 changes: 12 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@ func serve(ctx context.Context, db *DB, issuer issuerConfig, addr string) error
}
return h
}, cookiesession.Options{
MaxAge: 0, // Scopes it to browser lifecycle, which I think is good for now
Path: "/",
MaxAge: 0, // Scopes it to browser lifecycle, which I think is good for now
Path: "/",
SameSite: http.SameSiteLaxMode,
Insecure: issuer.URL.Hostname() == "localhost", // safari is picky about this
})
if err != nil {
return fmt.Errorf("creating cookie session for webauthn: %w", err)
Expand All @@ -193,16 +195,15 @@ func serve(ctx context.Context, db *DB, issuer issuerConfig, addr string) error

heh := &httpErrHandler{}

// TODO - usernameless via resident keys would be nice, but need to
// see what support is like.
rrk := false
wn, err := webauthn.New(&webauthn.Config{
RPDisplayName: issuer.URL.Hostname(), // Display Name for your site
RPID: issuer.URL.Hostname(), // Generally the FQDN for your site
RPOrigin: issuer.URL.String(), // The origin URL for WebAuthn requests
RPOrigins: []string{
issuer.URL.String(),
},
AuthenticatorSelection: protocol.AuthenticatorSelection{
UserVerification: protocol.VerificationRequired,
RequireResidentKey: &rrk,
RequireResidentKey: ptr(true),
},
})
if err != nil {
Expand Down Expand Up @@ -342,3 +343,7 @@ func fatalf(s string, args ...any) {
func logErr(err error) slog.Attr {
return slog.Any("error", err)
}

func ptr[T any](v T) *T {
return &v
}
28 changes: 4 additions & 24 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"embed"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -122,38 +121,19 @@ func (s *oidcServer) AddHandlers(mux *http.ServeMux) {
}

func (s *oidcServer) startLogin(rw http.ResponseWriter, req *http.Request) {
// A lot of this is lifted from the webauthn.BeginLogin message, but doing it
// directly because we aren't hinting the user.

challenge, err := protocol.CreateChallenge()
response, sessionData, err := s.webauthn.BeginDiscoverableLogin(webauthn.WithUserVerification(protocol.VerificationRequired))
if err != nil {
s.httpErr(rw, err)
slog.Error("starting discoverable login", logErr(err))
s.httpErr(rw, errors.New("no active login session"))
return
}

requestOptions := protocol.PublicKeyCredentialRequestOptions{
Challenge: challenge,
Timeout: int(s.webauthn.Config.Timeouts.Login.Timeout),
RelyingPartyID: s.webauthn.Config.RPID,
UserVerification: s.webauthn.Config.AuthenticatorSelection.UserVerification,
// AllowedCredentials: allowedCredentials, // this is what we don't send for resident/usernameless
}

sessionData := webauthn.SessionData{
Challenge: base64.RawURLEncoding.EncodeToString(challenge),
// UserID: user.WebAuthnID(),
AllowedCredentialIDs: requestOptions.GetAllowedCredentialIDs(),
UserVerification: requestOptions.UserVerification,
}

response := protocol.CredentialAssertion{Response: requestOptions}

sess := s.sessmgr.Get(req.Context())
if sess.WebauthnLogin == nil {
s.httpErr(rw, errors.New("no active login session"))
return
}
sess.WebauthnLogin.WebauthnSessionData = &sessionData
sess.WebauthnLogin.WebauthnSessionData = sessionData
s.sessmgr.Save(req.Context(), sess)

if err := json.NewEncoder(rw).Encode(response); err != nil {
Expand Down

0 comments on commit 69d0412

Please sign in to comment.