-
I'm merging Hydra and Kratos in a demo setup using a Python ui. Most of the things
For what is worth, the client is an # run_test_client.sh
name=${1:? "At least a first parameter for the name of the client is required"}
secret=${2:-"secret"}
port=${3:-"5555"}
echo -e "Starting a demo client on port: \"$port\", \n with id: \"$name\" and secret: \"$secret\"..."
arion exec hydra -- hydra token user \
--endpoint http://127.0.0.1:4444/ \
--client-id $name \
--client-secret $secret \
--port $port \
--scope openid,offline and the client itself is created with another script: # create_test_client.sh
name=${1:? "At least a first parameter for the name of the client is required"}
secret=${2:-"secret"}
cback=${3:-"http://127.0.0.1:5555/callback"}
echo "Creating a new client with id: \"$name\" and secret: \"$secret\"..."
arion exec hydra -- hydra clients create \
--endpoint http://127.0.0.1:4445/ \
--id $name \
--secret $secret \
--grant-types authorization_code,refresh_token \
--response-types code,id_token \
--scope openid,offline \
--callbacks $cback So usually i run the client with:
Any clue about how to investigate further? This is my testing Hydra config: ## ORY Hydra Configuration
version: v1.10.7
serve:
cookies:
same_site_mode: Lax
# public:
# cors:
# enabled: true
dsn: postgres://auth:secret@hydra-db:5432/hydra?sslmode=disable&max_conns=20&max_idle_conns=4
oidc:
subject_identifiers:
supported_types:
- public
- pairwise
pairwise:
salt: youReallyNeedToChangeThis
urls:
login: http://127.0.0.1:4455/auth/login
consent: http://127.0.0.1:4455/auth/consent
logout: http://127.0.0.1:4455/consent
error: http://127.0.0.1:4455/error
post_logout_redirect: http://127.0.0.1:3000/
self:
public: http://127.0.0.1:4444/
issuer: http://127.0.0.1:4444/
ttl:
access_token: 1h
refresh_token: 1h
id_token: 1h
auth_code: 1h
oauth2:
expose_internal_errors: true
secrets:
cookie:
- youReallyNeedToChangeThis
system:
- youReallyNeedToChangexhis
log:
leak_sensitive_values: true
format: text
level: debug Is there a way to let Hydra better explain the cause of the error? The following is the log of my app for what happens when clicking on the authentication link of the client (this shows both the Hydra and Kratos interaction):
And this is the Hydra log for the same process:
The
Any idea? thanks in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 4 replies
-
If needed I can show the source of my Python script that serves the UI, but I must advise that it's using a different API client library, because it's using an async model |
Beta Was this translation helpful? Give feedback.
-
I tried with a very simple Hydra login endpoint that immediately accepts the login request, and it shows the same problem. That was unexpected! And sad :-/ I'll post the Python source of the endpoint:ù @jp.SetRoute('/auth/login')
async def oauth_login_shallow(request):
"""
Hydra login entry point
"""
page = jp.WebPage(title="Welcome to the OAuth login page")
challenge = request.query_params.get('login_challenge')
print("\nNew OAuth shallow login request")
if not challenge:
print(f"Hydra login challenge missing")
page + jp.H1(text="Error, Missing 'login_challenge' query parameter")
return page
log_req = await get_login_request.asyncio(client=h_client,
login_challenge=challenge)
if isinstance(log_req, ContainsInformationOnAnOngoingLoginRequest):
print(f"The login_challenge {challenge!r} is valid")
if log_req.skip: print("skip")
else:
print(f"Error authenticating login_challenge")
page + jp.H1(text="Error, unauthorized oauth client (login_challenge is fake?)!")
return page
body = HandledLoginRequestIsTheRequestPayloadUsedToAcceptALoginRequest(
subject="shallow_subject",
)
print(f"Signal Hydra to accept auth requesto for challenge: {challenge!r}")
accept_resp = await accept_login_request.asyncio(
client=h_client,
login_challenge=challenge,
json_body=body
)
if isinstance(
accept_resp,
TheResponsePayloadSentWhenAcceptingOrRejectingALoginOrConsentRequest):
page.redirect = accept_resp.redirect_to
print(f"Got consent redirect from Hydra to {page.redirect!r}")
else:
raise RuntimeError("Error while accepting hydra challenge")
return page + jp.H1(text="Redirect to consent flow") Probably it's something so simple that I can't see it.... |
Beta Was this translation helpful? Give feedback.
-
Hello Alberto, |
Beta Was this translation helpful? Give feedback.
-
Hi @vinckr, thanks for answering. Unfortunately it was a bug of the small Python library that I'm using to generate the pages, see justpy-org/justpy#335 . No it works to the end! Nice! Even the joined Hydra-Kratos workflow works (with external github authentication)! Now the test client at the end of the process writes:
Shouldn't the IDToken show something? |
Beta Was this translation helpful? Give feedback.
-
Nailed it with a "consent all" consent endpoint like: @jp.SetRoute('/auth/consent')
async def oauth_consent(request):
"""
Hydra consent entry point
"""
page = jp.WebPage(title="Welcome to the OAuth consent page")
page + jp.H1(text="Consent page")
challenge = request.query_params.get('consent_challenge')
print("New OAuth consent request")
if not challenge:
print(f"Hydra consent challenge missing")
page + jp.H1(text="Error, Missing 'consent_challenge' query parameter")
return page
con_req = await get_consent_request.asyncio(client=h_client,
consent_challenge=challenge)
if isinstance(con_req, ContainsInformationOnAnOngoingConsentRequest):
print(f"The consent_challenge {challenge!r} is valid")
else:
print(f"Error authenticating consent_challenge")
page + jp.H1(text="Error, unauthorized oauth client (consent_challenge is fake?)!")
return page
session = await _get_kratos_session(request)
if _kratos_session_is_valid(session):
print(f"Accepting consent request {challenge!r}")
accept_resp = await accept_consent_request.asyncio(
client=h_client, consent_challenge=challenge,
json_body=TheRequestPayloadUsedToAcceptAConsentRequest(
grant_scope=con_req.requested_scope))
if isinstance(
accept_resp,
TheResponsePayloadSentWhenAcceptingOrRejectingALoginOrConsentRequest):
dest = accept_resp.redirect_to
print(f"Got final redirect from Hydra to {dest!r}")
page.redirect = dest
return (page + jp.H1(text="Kratos login redirect to Hydra"))
else:
raise RuntimeError("Error while accepting hydra challenge")
return page The key is to "copy" the requested scopes to those granted. Now at the end I get:
|
Beta Was this translation helpful? Give feedback.
-
@azazel75 |
Beta Was this translation helpful? Give feedback.
Nailed it with a "consent all" consent endpoint like: