How to avoid additional verification when using OAuth2 authentication flow for first-party applications? #139
-
|
I am developing a POC with two apps. One is a custom accounts app that utilizes the ory kratos and hydra that handles the UI and other account related actions. The other one is a so called console app. Since console is a first party app I wish to skip oauth and logout consent. I did all that and works great, except one thing. If I am already authenticated in the accounts app (accounts.local) before visiting the console app (console.local) and I initiate OAuth authentication flow, I get redirected to login and must enter a password with a message "Please confirm this action by verifying that it is you.". I can't for the life of me figure out how to skip this verification, since this is a first-party app and I don't need any consent or verification if the user is already authenticated. I've been at it the for two days now... From what I was able to figure out, when first redirecting from console.local, the browser does not have Bellow is a full flow with url redirects and configs so you can see what is going on and also my discovery journey at bottom. OAuth2 client creation.docker compose exec hydra hydra create client --endpoint http://127.0.0.1:4445/ --format json \
--grant-type authorization_code \
--name console \
--redirect-uri http://console.local/callback \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method client_secret_post \
--skip-consent \
--skip-logout-consent \
--post-logout-callback http://console.localInitial login into accounts.local appVisiting console.local OAuth client appVisiting console.local again after clearing app session cookieKratos configversion: v0.13.0
dsn: memory
serve:
public:
base_url: http://accounts.local/auth
cors:
enabled: true
admin:
base_url: http://kratos:4434/
selfservice:
default_browser_return_url: http://accounts.local/
allowed_return_urls:
- http://accounts.local
methods:
password:
enabled: true
totp:
config:
issuer: POC
enabled: true
lookup_secret:
enabled: true
link:
enabled: true
code:
enabled: true
flows:
error:
ui_url: http://accounts.local/auth/error
settings:
ui_url: http://accounts.local
privileged_session_max_age: 15m
required_aal: highest_available
recovery:
enabled: true
ui_url: http://accounts.local/auth/recovery
use: code
verification:
enabled: true
ui_url: http://accounts.local/auth/verification
use: code
after:
default_browser_return_url: http://accounts.local/
logout:
after:
default_browser_return_url: http://accounts.local/auth/login
login:
ui_url: http://accounts.local/auth/login
lifespan: 10m
# style: identifier_first
registration:
lifespan: 10m
ui_url: http://accounts.local/auth/registration
after:
password:
hooks:
- hook: session
- hook: show_verification_ui
log:
level: debug
format: text
leak_sensitive_values: true
secrets:
cookie:
- PLEASE-CHANGE-ME-I-AM-VERY-INSECURE
cipher:
- 32-LONG-SECRET-NOT-SECURE-AT-ALL
ciphers:
algorithm: xchacha20-poly1305
hashers:
algorithm: bcrypt
bcrypt:
cost: 8
identity:
default_schema_id: default
schemas:
- id: default
url: file:///etc/config/kratos/identity.schema.json
courier:
message_retries: 28800 #
worker:
pull_wait: 5s
smtp:
connection_uri: smtps://test:test@mailslurper:1025/?skip_ssl_verify=true
feature_flags:
use_continue_with_transitions: true
oauth2_provider:
url: http://hydra:4445
session:
cookie:
persistent: true
Hydra configlog:
level: debug
leak_sensitive_values: true
dsn: sqlite://data/db.sqlite?_fk=true&mode=rwc
serve:
cookies:
same_site_mode: Lax
urls:
self:
issuer: http://accounts.local
consent: http://accounts.local/auth/consent
registration: http://accounts.local/auth/register
login: http://accounts.local/auth/login
logout: http://accounts.local/auth/logout
error: http://accounts.local/auth/error
post_logout_redirect: http://accounts.local/auth/logout-successful
identity_provider:
publicUrl: http://kratos:4433
url: http://kratos:4434
secrets:
system:
- youReallyNeedToChangeThis
oidc:
subject_identifiers:
supported_types:
- pairwise
- public
pairwise:
salt: youReallyNeedToChangeThis
My discovery journeyWhen I compared flows with and without having It took a while to get here. I didn't see that kratos was adding The requirement for verification is caused by kratos adding refresh to redirect query because the hydra login request skip is false. Here I am stuck. Examining the source code, the only way to skip verification is to have |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
Finally figured it out. I don't know if this violates any best security practices but I did the following: func (s *Auth) LoginGET(c fiber.Ctx) error {
loginChallenge := c.Query("login_challenge")
session := session.GetSession(c)
if loginChallenge != "" {
if session != nil {
// if ory hydra login_challenge and session exists, accept login request
alReq := hydra.NewAcceptOAuth2LoginRequest(session.Identity.Id)
alReq.IdentityProviderSessionId = &session.Id
alReq.Remember = x.Ptr(true)
for _, r := range session.AuthenticationMethods {
alReq.Amr = append(alReq.Amr, r.GetMethod())
}
alRes, _, err := s.hydraAdmin.OAuth2API.AcceptOAuth2LoginRequest(c).LoginChallenge(loginChallenge).AcceptOAuth2LoginRequest(*alReq).Execute()
if err != nil {
return fmt.Errorf("failed to accept OAuth2 login request: %w", err)
}
return c.Redirect().To(alRes.RedirectTo)
}
if c.Query("flow") == "" {
return s.kratos.ProxySelfServiceRequest(c, kratos.LoginSelfServiceEndpoint)
}
}
loginFlow, err := s.kratos.LoadLoginFlow(c)
if err != nil {
return fmt.Errorf("failed to initiate login flow: %w", err)
}
return Render(c, "Login", authView.LoginPage(&loginFlow.Ui, s.url.register, s.url.recover), nil)
}This is basically what Kratos does after one verifies their identity before redirecting back to hydra. I just implemented this in my |
Beta Was this translation helpful? Give feedback.
Finally figured it out. I don't know if this violates any best security practices but I did the following: