Finish KEY-WP-0008: registration handoff and client MFA isolation
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 34s
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 34s
Add signed registration/enrollment handoffs, per-request assurance policy with login-session isolation, and /logout. coulomb-social stays AAL1 unless acr_values or another client raises the bar.
This commit is contained in:
parent
fff9e39478
commit
b6af6c5268
22 changed files with 1636 additions and 42 deletions
|
|
@ -41,7 +41,17 @@ func (a *PrivacyIDEAAdapter) CheckMFARequired(ctx context.Context, userID string
|
|||
if a.cfg.RequireForAll {
|
||||
return true, nil
|
||||
}
|
||||
return a.hasActiveToken(ctx, userID)
|
||||
}
|
||||
|
||||
// HasEnrolledFactor reports whether privacyIDEA has an active token for the
|
||||
// user. RequireForAll does not skip this check — enrollment is independent
|
||||
// of the global require-for-all policy.
|
||||
func (a *PrivacyIDEAAdapter) HasEnrolledFactor(ctx context.Context, userID string) (bool, error) {
|
||||
return a.hasActiveToken(ctx, userID)
|
||||
}
|
||||
|
||||
func (a *PrivacyIDEAAdapter) hasActiveToken(ctx context.Context, userID string) (bool, error) {
|
||||
endpoint := strings.TrimRight(a.cfg.BaseURL, "/") + "/token/"
|
||||
|
||||
q := url.Values{}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,48 @@ func TestCheckMFARequired_InactiveTokenOnly_ReturnsFalse(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestHasEnrolledFactor_RequireForAllStillListsTokens(t *testing.T) {
|
||||
called := false
|
||||
client := &mockHTTPClient{
|
||||
doFn: func(_ *http.Request) (*http.Response, error) {
|
||||
called = true
|
||||
return jsonResponse(tokenListResponse(nil)), nil
|
||||
},
|
||||
}
|
||||
cfg := testConfig()
|
||||
cfg.RequireForAll = true
|
||||
adapter := privacyidea.New(cfg, client)
|
||||
|
||||
enrolled, err := adapter.HasEnrolledFactor(context.Background(), "alice")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if enrolled {
|
||||
t.Error("expected enrolled=false when no tokens even if RequireForAll")
|
||||
}
|
||||
if !called {
|
||||
t.Error("HasEnrolledFactor must consult the token list")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasEnrolledFactor_ActiveToken_ReturnsTrue(t *testing.T) {
|
||||
client := &mockHTTPClient{
|
||||
doFn: func(_ *http.Request) (*http.Response, error) {
|
||||
return jsonResponse(tokenListResponse([]map[string]interface{}{
|
||||
{"active": true},
|
||||
})), nil
|
||||
},
|
||||
}
|
||||
adapter := privacyidea.New(testConfig(), client)
|
||||
enrolled, err := adapter.HasEnrolledFactor(context.Background(), "alice")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !enrolled {
|
||||
t.Error("expected enrolled=true when an active token is present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckMFARequired_NoTokens_ReturnsFalse(t *testing.T) {
|
||||
client := &mockHTTPClient{
|
||||
doFn: func(_ *http.Request) (*http.Response, error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue