{"record":{"id":"0590619ee78d549b","repo":"ory/hydra","slug":"flow-forcesubjectidentifier-s-does-not-match-the","errorCode":null,"errorMessage":"flow ForceSubjectIdentifier %s does not match the HandledLoginRequest ForceSubjectIdentifier %s","messagePattern":"flow ForceSubjectIdentifier (.+?) does not match the HandledLoginRequest ForceSubjectIdentifier (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"flow/flow.go","lineNumber":314,"sourceCode":"func (f *Flow) InvalidateDeviceRequest() error {\n\tif err := f.State.IsAny(DeviceFlowStateUnused); err != nil {\n\t\treturn err\n\t}\n\tf.State = DeviceFlowStateUsed\n\treturn nil\n}\n\nfunc (f *Flow) HandleLoginRequest(h *HandledLoginRequest) error {\n\tif err := f.State.IsAny(FlowStateLoginInitialized, FlowStateLoginUnused, FlowStateLoginError); err != nil {\n\t\treturn err\n\t}\n\n\tif f.Subject != \"\" && h.Subject != \"\" && f.Subject != h.Subject {\n\t\treturn errors.Errorf(\"flow Subject %s does not match the HandledLoginRequest Subject %s\", f.Subject, h.Subject)\n\t}\n\n\tif f.ForceSubjectIdentifier != \"\" && h.ForceSubjectIdentifier != \"\" && f.ForceSubjectIdentifier != h.ForceSubjectIdentifier {\n\t\treturn errors.Errorf(\"flow ForceSubjectIdentifier %s does not match the HandledLoginRequest ForceSubjectIdentifier %s\", f.ForceSubjectIdentifier, h.ForceSubjectIdentifier)\n\t}\n\n\tf.State = FlowStateLoginUnused\n\n\tif f.Context != nil {\n\t\tf.Context = h.Context\n\t}\n\n\tf.Subject = h.Subject\n\tf.ForceSubjectIdentifier = h.ForceSubjectIdentifier\n\n\tf.IdentityProviderSessionID = sqlxx.NullString(h.IdentityProviderSessionID)\n\tf.LoginRemember = h.Remember\n\tf.LoginRememberFor = h.RememberFor\n\tf.LoginExtendSessionLifespan = h.ExtendSessionLifespan\n\tf.ACR = h.ACR\n\tf.AMR = h.AMR\n\treturn nil","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/flow/flow.go#L296-L332","documentation":"Flow.HandleLoginRequest also verifies ForceSubjectIdentifier: if both the Flow and the HandledLoginRequest carry a non-empty ForceSubjectIdentifier they must be identical. This field is set when an upstream flow (e.g. a previous authentication or ID token hint) forced a specific subject, and mismatch means the login was accepted for a different identity than forced.","triggerScenarios":"Calling HandleLoginRequest when f.ForceSubjectIdentifier and h.ForceSubjectIdentifier are both set but differ — typically when id_token_hint or a forced subject from an earlier step conflicts with the user that actually authenticated.","commonSituations":"Using id_token_hint for silent re-authentication but the session belongs to another user; a subject was forced by consent/previous authentication but the login handler let the user log in with a different account; mixing flow objects between requests.","solutions":["Make the login provider enforce the forced subject (auto-select/pre-authenticate that user) so h.ForceSubjectIdentifier matches the flow","If the forced subject cannot be satisfied, fail the login with an error instead of accepting a different identity","If forcing is no longer desired, create a new login flow without ForceSubjectIdentifier set","Verify you are not copying fields from a different flow into the HandledLoginRequest"],"exampleFix":"// before\nhandled := &flow.HandledLoginRequest{Subject: session.Subject, ForceSubjectIdentifier: session.Subject}\nerr := flow.HandleLoginRequest(handled)\n// after\nif flow.ForceSubjectIdentifier != \"\" && flow.ForceSubjectIdentifier != session.Subject {\n    return errors.New(\"forced subject does not match authenticated user\") // reject login\n}\nhandled.ForceSubjectIdentifier = flow.ForceSubjectIdentifier\nerr := flow.HandleLoginRequest(handled)","handlingStrategy":"validation","validationCode":"if flow.ForceSubjectIdentifier != \"\" {\n    if session.Subject != flow.ForceSubjectIdentifier {\n        return errors.New(\"forced subject mismatch: user must re-authenticate as the forced identity\")\n    }\n    handled.ForceSubjectIdentifier = flow.ForceSubjectIdentifier\n}\nerr := flow.HandleLoginRequest(handled)","typeGuard":null,"tryCatchPattern":"if err := flow.HandleLoginRequest(handled); err != nil {\n    if strings.Contains(err.Error(), \"ForceSubjectIdentifier\") {\n        return redirectToLoginWithError(\"please authenticate with the required account\")\n    }\n    return err\n}","preventionTips":["When a flow carries ForceSubjectIdentifier, enforce single-sign-on/auto-login for exactly that subject","Never let the login UI allow choosing a different account when a subject is forced (use max_age/prompt=none semantics)","Propagate the forced subject through your login provider instead of regenerating it from the current session","Test the id_token_hint flow with a session for a different user to catch mismatches"],"tags":["oauth2","oidc","hydra","login-flow","force-subject-identifier"],"backgroundTag":"login-subject-mismatch","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}