proxy: add userinfo and webauthn endpoints (#3755)

* proxy: add userinfo and webauthn endpoints

* use TLD for RP id

* use EffectiveTLDPlusOne

* upgrade webauthn

* fix test

* Update internal/handlers/jwks.go

Co-authored-by: bobby <1544881+desimone@users.noreply.github.com>

Co-authored-by: bobby <1544881+desimone@users.noreply.github.com>
This commit is contained in:
Caleb Doxsey 2022-11-22 10:26:35 -07:00 committed by GitHub
parent 81053ac8ef
commit c1a522cd82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 498 additions and 216 deletions

View file

@ -3,6 +3,7 @@ package webauthnutil
import (
"encoding/base64"
"fmt"
"net/http"
"time"
"github.com/pomerium/webauthn"
@ -25,12 +26,14 @@ func GenerateChallenge(key []byte, expiry time.Time) cryptutil.SecureToken {
// GenerateCreationOptions generates creation options for WebAuthn.
func GenerateCreationOptions(
r *http.Request,
key []byte,
deviceType *device.Type,
user *user.User,
) *webauthn.PublicKeyCredentialCreationOptions {
expiry := time.Now().Add(ceremonyTimeout)
return newCreationOptions(
r,
GenerateChallenge(key, expiry).Bytes(),
deviceType,
user,
@ -39,12 +42,14 @@ func GenerateCreationOptions(
// GenerateRequestOptions generates request options for WebAuthn.
func GenerateRequestOptions(
r *http.Request,
key []byte,
deviceType *device.Type,
knownDeviceCredentials []*device.Credential,
) *webauthn.PublicKeyCredentialRequestOptions {
expiry := time.Now().Add(ceremonyTimeout)
return newRequestOptions(
r,
GenerateChallenge(key, expiry).Bytes(),
deviceType,
knownDeviceCredentials,
@ -54,6 +59,7 @@ func GenerateRequestOptions(
// GetCreationOptionsForCredential gets the creation options for the public key creation credential. An error may be
// returned if the challenge used to generate the credential is invalid.
func GetCreationOptionsForCredential(
r *http.Request,
key []byte,
deviceType *device.Type,
user *user.User,
@ -76,12 +82,13 @@ func GetCreationOptionsForCredential(
return nil, err
}
return newCreationOptions(challenge.Bytes(), deviceType, user), nil
return newCreationOptions(r, challenge.Bytes(), deviceType, user), nil
}
// GetRequestOptionsForCredential gets the request options for the public key request credential. An error may be
// returned if the challenge used to generate the credential is invalid.
func GetRequestOptionsForCredential(
r *http.Request,
key []byte,
deviceType *device.Type,
knownDeviceCredentials []*device.Credential,
@ -104,11 +111,12 @@ func GetRequestOptionsForCredential(
return nil, err
}
return newRequestOptions(challenge.Bytes(), deviceType, knownDeviceCredentials), nil
return newRequestOptions(r, challenge.Bytes(), deviceType, knownDeviceCredentials), nil
}
// newCreationOptions gets the creation options for WebAuthn with the provided challenge.
func newCreationOptions(
r *http.Request,
challenge []byte,
deviceType *device.Type,
user *user.User,
@ -116,6 +124,7 @@ func newCreationOptions(
options := &webauthn.PublicKeyCredentialCreationOptions{
RP: webauthn.PublicKeyCredentialRPEntity{
Name: rpName,
ID: GetEffectiveDomain(r),
},
User: GetUserEntity(user),
Challenge: challenge,
@ -133,6 +142,7 @@ func newCreationOptions(
// newRequestOptions gets the request options for WebAuthn with the provided challenge.
func newRequestOptions(
r *http.Request,
challenge []byte,
deviceType *device.Type,
knownDeviceCredentials []*device.Credential,
@ -140,6 +150,7 @@ func newRequestOptions(
options := &webauthn.PublicKeyCredentialRequestOptions{
Challenge: challenge,
Timeout: ceremonyTimeout,
RPID: GetEffectiveDomain(r),
}
fillRequestUserVerificationRequirement(
options,