diff --git a/internal/data/config.go b/internal/data/config.go index 8514f671..29e55159 100644 --- a/internal/data/config.go +++ b/internal/data/config.go @@ -13,10 +13,11 @@ import ( ) type OIDC struct { - IssuerURL string - ClientSecret string - ClientID string - GroupsClaimName string + IssuerURL string + ClientSecret string + ClientID string + GroupsClaimName string + DeviceUsernameClaim string } type PAM struct { diff --git a/internal/users/user.go b/internal/users/user.go index 3fac5423..8de44e5b 100644 --- a/internal/users/user.go +++ b/internal/users/user.go @@ -3,7 +3,6 @@ package users import ( "errors" "fmt" - "log" "net" "github.com/NHAS/wag/internal/data" @@ -121,8 +120,6 @@ func (u *user) Authenticate(device, mfaType string, authenticator types.Authenti return errors.New("could not get lockout value") } - log.Println("mfa: ", mfa, "type:", userMfaType, "attempts: ", attempts, "locked: ", locked, "lockout: ", lockout) - if attempts >= lockout { return errors.New("device is locked") } diff --git a/internal/webserver/authenticators/oidc.go b/internal/webserver/authenticators/oidc.go index 3c885b8f..023d5ca2 100644 --- a/internal/webserver/authenticators/oidc.go +++ b/internal/webserver/authenticators/oidc.go @@ -24,8 +24,7 @@ import ( ) type issuer struct { - Username string - Issuer string + Issuer string } type Oidc struct { @@ -121,14 +120,9 @@ func (o *Oidc) RegistrationAPI(w http.ResponseWriter, r *http.Request) { log.Println(user.Username, clientTunnelIp, "registering with oidc") - // The MFA value column is set to unique (which is important for the totp and webauthn methods), so for this we need to be a bit hacky and make sure that we add the username which is also unique - - issuer := issuer{ - Username: user.Username, - Issuer: o.provider.Issuer(), - } - - value, _ := json.Marshal(issuer) + value, _ := json.Marshal(issuer{ + Issuer: o.provider.Issuer(), + }) err = data.SetUserMfa(user.Username, string(value), o.Type()) if err != nil { @@ -168,6 +162,21 @@ func (o *Oidc) AuthorisationAPI(w http.ResponseWriter, r *http.Request) { return } + deviceUsername := info.GetPreferredUsername() + + if len(o.details.DeviceUsernameClaim) != 0 { + + deviceUsernameClaim, ok := tokens.IDTokenClaims.GetClaim(o.details.DeviceUsernameClaim).(string) + if !ok { + log.Println("Error, Device Username Claim set but idP has not set attribute in users token") + http.Error(w, "Server Error", http.StatusInternalServerError) + return + } + + deviceUsername = deviceUsernameClaim + + } + // Rather ugly way of converting []interface{} into []string{} groups := []string{} for i := range groupsIntf { @@ -193,7 +202,8 @@ func (o *Oidc) AuthorisationAPI(w http.ResponseWriter, r *http.Request) { return errors.New("stored issuer " + issuerDetails.Issuer + " did not equal actual issuer: " + rp.Issuer()) } - if info.GetPreferredUsername() != username { + if deviceUsername != username { + log.Printf("Error logging in user, idP supplied device username (%s) does not equal expected username (%s)", deviceUsername, username) return errors.New("user is not associated with device") } diff --git a/ui/src/js/settings.js b/ui/src/js/settings.js index ef525d03..1212d79f 100644 --- a/ui/src/js/settings.js +++ b/ui/src/js/settings.js @@ -66,6 +66,7 @@ $(function () { "ClientSecret": $('#oidcClientSecret').val(), "ClientID": $('#oidcClientID').val(), "GroupsClaimName": $('#oidcGroupsClaimName').val(), + "DeviceUsernameClaim": $("#oidcDeviceUsernameClaim").val(), }, "PamDetails": { "ServiceName": $('#pamServiceName').val(), diff --git a/ui/templates/settings/general.html b/ui/templates/settings/general.html index fb9fe8cd..87a5842d 100755 --- a/ui/templates/settings/general.html +++ b/ui/templates/settings/general.html @@ -146,7 +146,13 @@