Closed sczj closed 2 years ago
@aeneasr on a side note, do you plan a tagged release with this change anytime soon or there's something else that you'd like to merge first?
Wow! This is great! Any idea when there'll be a release @aeneasr?
- hydra v2.0.1 with urls.consent pointing to consent API as usual and login/logout URLs pointing to Kratos' selfservice UI
@dezeroku, what did you use as the logout URL in the hydra config? The Kratos self-service UI doesn't have a specific logout endpoint and generates the logout link dynamically. My hydra.yml
looks like this:
serve:
cookies:
same_site_mode: Lax
urls:
self:
issuer: http://127.0.0.1:4444
consent: http://127.0.0.1:3000/consent
login: http://127.0.0.1:4455/login
logout: http://127.0.0.1:4455/logout # will not work??
secrets:
system:
- youReallyNeedToChangeThis
oidc:
subject_identifiers:
supported_types:
- pairwise
- public
pairwise:
salt: youReallyNeedToChangeThis
@sidharthramesh I am afraid you're right, I've used the selfservice's /logout (nonexistent) endpoint in hydra configuration and never really got around to testing it. At this state of testing I was mostly using Kratos' logout option on selfservice's welcome page and cleaning cookies from time to time.
I think a good starting point would be to use the /logout endpoint from the consent app? And if you get into a weird login redirection loop in which:
you might consider modifying the logic in https://github.com/ory/hydra-login-consent-node/blob/master/src/routes/logout.ts#L63 to also redirect to Kratos' logout URL defined as in selfservice: https://github.com/ory/kratos-selfservice-ui-node/blob/master/src/routes/welcome.ts#L22 Not sure if this would be needed at all or Hydra would handle both Hydra and Kratos "sessions" logout behind the scenes.
This is where official versions and guide is required, of course we may all together try to solve those issues, and reverse ingeener all of those, even looking at the code but those problems were already solved. @aeneasr could you tell us about plans? Is there a plan to publish it (versions and guide) or there was some decision change to not publish it to open community right now?
I've been able to integrate kratos as IDP provider for hydra and it works beautifully after kratos 0.11.0
release. Thanks so much for the great work you do guys!
One issue I encountered while implementing is that the oauth2_provider.url
is being used when communicating with both hydra public and admin endpoints. In our production setup, hydra admin endpoints are not accessible publicly and are served through a different url than the public endpoints.
Thus when kratos tried to access hydra admin endpoint (to get login_challenge
details) using the public url configured in oauth2_provider.url
, it reported a 404 error. I was able to fix that using an nginx rewrite rule for now, but it would be nice to have a separate config maybe oauth2_provider.admin_url
or so.
Hey, that is good to hear @genedy2017 ! If you ever want to do a writeup of your setup for other community members, feel free to reach out to me :)
As for your issue, I think it would be best if you open a new discussion (or even a bug report?) for it. Some crazies like me follow all the threads, but maintainers mainly look at new issues or discussions.
Hey @vinckr,
If you ever want to do a writeup of your setup for other community members, feel free to reach out to me :)
Would love to! I'll prepare an article and reach out to you within a few weeks.
I'll open a new issue as per your recommendation.
@bbroniewski it works for me (meaning I can obtain tokens from hydra, based on Kratos' user data/login process) with the following config:
1. kratos docker image built from master, oauth2_provider.url in config set to hydra's admin API 2. consent v2.0.1, pointing to Hydra's admin/public API as usual 3. kratos' selfservice UI image :latest, pointing to kratos admin/public API as usual 4. hydra v2.0.1 with urls.consent pointing to consent API as usual and login/logout URLs pointing to Kratos' selfservice UI
What confuses me about "2.", that why do I need the hydra "consent" user-interface if I use the kratos ui for login and logout?
@LasseRosenow If I remember correctly, kratos ui didn't have "consent" screen implemented at the time (maybe it's changed now, I don't know). So for the "full OAuth experience" you needed both login screen (kratos UI) and consent screen (consent service)
Hey @vinckr,
If you ever want to do a writeup of your setup for other community members, feel free to reach out to me :)
Would love to! I'll prepare an article and reach out to you within a few weeks.
I'll open a new issue as per your recommendation.
I'm new to install Kratos and Hydra implementation, wondering if there's a guide that anyone can share?
Hello @muwiess Check out this discussion for the "status quo": https://github.com/ory/kratos/discussions/2976#discussioncomment-4507555
There is no "out-of-the-box" guide yet, but there are a lot of examples around. If you would like to contribute a guide for the self-hosted integration of Kratos/Hydra, I would be happy to help you! Otherwise you can test out the integration without any previous for on the managed Ory Network
@muwiess were you able to get this working ? If so, do you have any docs we can steal ? :)
@bbroniewski it works for me (meaning I can obtain tokens from hydra, based on Kratos' user data/login process) with the following config:
- kratos docker image built from master, oauth2_provider.url in config set to hydra's admin API
- consent v2.0.1, pointing to Hydra's admin/public API as usual
- kratos' selfservice UI image :latest, pointing to kratos admin/public API as usual
- hydra v2.0.1 with urls.consent pointing to consent API as usual and login/logout URLs pointing to Kratos' selfservice UI
@dezeroku I'm struggling to get this to work. I have tried integrating Hydra/Kratos login flow using hydra-login-consent-node
+ kratos-selfservice-ui-node
, and also my custom UI.
docker compose file:
name: ory
networks:
postgres:
external: true
name: postgres_internal
public:
external: true
name: public
mailhog:
external: true
name: mailhog_internal
volumes:
kratos:
name: kratos_data
x-kratos-volumes: &kratos-volumes
volumes:
- ${DEV_CONFIG_DIR}/kratos:/etc/config/kratos
- kratos:/var/lib/sqlite
- kratos:/home/ory
services:
kratos-migrate:
# image: oryd/kratos:${KRATOS_VERSION}
image: ellicodan/kratos:latest
container_name: ${KRATOS_HOST_NAME}-migrate
<<: *kratos-volumes
command: --config /etc/config/kratos/kratos.yml migrate sql --read-from-env --yes
environment:
- DSN=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST_NAME}:${POSTGRES_PORT}/${KRATOS_DB_NAME}?sslmode=disable&max_conns=20&max_idle_conns=4
- LOG_LEVEL=info
networks:
- postgres
hydra-migrate:
image: oryd/hydra:$HYDRA_VERSION
container_name: ${HYDRA_HOST_NAME}-migrate
command: migrate sql --read-from-env --yes
environment:
- DSN=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST_NAME}:${POSTGRES_PORT}/${HYDRA_DB_NAME}?sslmode=disable&max_conns=20&max_idle_conns=4
networks:
- postgres
kratos:
# image: oryd/kratos:${KRATOS_VERSION}
image: ellicodan/kratos:latest
container_name: ${KRATOS_HOST_NAME}
<<: *kratos-volumes
command: serve --config /etc/config/kratos/kratos.yml --watch-courier --dev
environment:
- DSN=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST_NAME}:${POSTGRES_PORT}/${KRATOS_DB_NAME}?sslmode=disable&max_conns=20&max_idle_conns=4 # Postgresql
- LOG_LEVEL=info
networks:
- public
- postgres
- mailhog
ports:
- 4433:4433 # public
- 4434:4434 # admin
depends_on:
kratos-migrate:
condition: service_completed_successfully
hydra:
image: oryd/hydra:$HYDRA_VERSION
container_name: $HYDRA_HOST_NAME
volumes:
- ${DEV_CONFIG_DIR}/hydra:/etc/config/hydra
command: serve all --config /etc/config/hydra/hydra.yml --dev
environment:
- DSN=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST_NAME}:${POSTGRES_PORT}/${HYDRA_DB_NAME}?sslmode=disable&max_conns=20&max_idle_conns=4 # Postgresql
ports:
- 4444:4444 # public
- 4445:4445 # admin
- 5555:5555 # port for hydra token user
networks:
- public
- postgres
depends_on:
hydra-migrate:
condition: service_completed_successfully
kratos.yml file:
version: v0.11.1
dsn: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST_NAME}:${POSTGRES_PORT}/${KRATOS_DB_NAME}?sslmode=disable&max_conns=20&max_idle_conns=4
identity:
default_schema_id: customer_v1
schemas:
- id: customer_v1
url: file:///etc/config/kratos/customer.schema.json
log:
level: debug
format: text
leak_sensitive_values: true
serve:
public:
base_url: http://localhost:4433/
cors:
enabled: true
debug: true
admin:
base_url: http://localhost:4434/
selfservice:
default_browser_return_url: http://localhost:3000/
allowed_return_urls:
- http://localhost:3000
methods:
profile:
enabled: true
password:
enabled: true
config:
haveibeenpwned_enabled: true
haveibeenpwned_host: api.pwnedpasswords.com
max_breaches: 0
ignore_network_errors: true
min_password_length: 6
identifier_similarity_check_enabled: true
code:
enabled: true
config:
lifespan: 24h
link:
enabled: true
config:
lifespan: 24h
lookup_secret:
enabled: false
webauthn:
enabled: false
oidc:
enabled: false
flows:
login:
ui_url: http://localhost:3000/login
lifespan: 15m
logout:
after:
default_browser_return_url: http://localhost:3000/
registration:
ui_url: http://localhost:3000/registration
lifespan: 15m
after:
password:
hooks:
- hook: session
settings:
ui_url: http://localhost:3000/settings
privileged_session_max_age: 15m
required_aal: highest_available
after:
default_browser_return_url: http://localhost:3000/settings
recovery:
enabled: true
ui_url: http://localhost:3000/recovery
use: code
lifespan: 15m
after:
hooks:
- hook: revoke_active_sessions
verification:
enabled: true
ui_url: http://localhost:3000/verification
use: link
lifespan: 15m
after:
default_browser_return_url: http://localhost:3000/login
error:
ui_url: http://localhost:3000/error
oauth2_provider:
url: http://localhost:4445
headers:
Authorization: Bearer some-token
session:
lifespan: 1h
cookie:
name: ory-session
persistent: true
secrets:
cookie:
- PLEASE-CHANGE-ME-I-AM-VERY-INSECURE
cipher:
- 32-LONG-SECRET-NOT-SECURE-AT-ALL
ciphers:
algorithm: xchacha20-poly1305
hashers:
algorithm: argon2
argon2:
iterations: 3
memory: 64MB
parallelism: 4
key_length: 32
salt_length: 16
expected_duration: 500ms
expected_deviation: 500ms
dedicated_memory: 512MB
courier:
smtp:
connection_uri: smtp://mailhog:1026/?disable_starttls=true
hydra.yml file:
version: v2.0.3
dsn: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST_NAME}:${POSTGRES_PORT}/${HYDRA_DB_NAME}?sslmode=disable&max_conns=20&max_idle_conns=4
log:
leak_sensitive_values: true
format: text
level: debug
serve:
cookies:
same_site_mode: Lax
oidc:
subject_identifiers:
supported_types:
- public
- pairwise
pairwise:
salt: youReallyNeedToChangeThis
urls:
login: http://localhost:3000/login
logout: http://localhost:3000/logout
post_logout_redirect: http://localhost:3000/
consent: http://localhost:3001/consent
error: http://localhost:3000/error
self:
admin: https://localhost:4445/
public: http://localhost:4444/
issuer: http://localhost:4444/
ttl:
access_token: 1h
refresh_token: 1h
id_token: 1h
auth_code: 1h
oauth2:
expose_internal_errors: true
secrets:
cookie:
- youReallyNeedToChangeThis
system:
- youReallyNeedToChangexhis
Here is an example response that I receive for a login flow:
{
"id": "155217b1-3cd0-4ef1-a1d7-329f65b03071",
"oauth2_login_challenge": null,
"type": "browser",
"expires_at": "2023-03-23T05:31:24.562209Z",
"issued_at": "2023-03-23T05:16:24.562209Z",
"request_url": "http://localhost:4433/self-service/login/browser",
"ui": {
"action": "http://localhost:4433/self-service/login?flow=155217b1-3cd0-4ef1-a1d7-329f65b03071",
"method": "POST",
"nodes": [
{
"type": "input",
"group": "default",
"attributes": {
"name": "csrf_token",
"type": "hidden",
"value": "ogjV/+bvQFp7a8R+9aUR/Nx1podKqCJTh/Zdkmd0EtNwP+hoo71RFmziv6RA2wpqUKftalBOTP/DA12Nj5GJsQ==",
"required": true,
"disabled": false,
"node_type": "input"
},
"messages": [],
"meta": {}
},
{
"type": "input",
"group": "default",
"attributes": {
"name": "identifier",
"type": "text",
"value": "",
"required": true,
"disabled": false,
"node_type": "input"
},
"messages": [],
"meta": {
"label": {
"id": 1070004,
"text": "ID",
"type": "info"
}
}
},
{
"type": "input",
"group": "password",
"attributes": {
"name": "password",
"type": "password",
"required": true,
"autocomplete": "current-password",
"disabled": false,
"node_type": "input"
},
"messages": [],
"meta": {
"label": {
"id": 1070001,
"text": "Password",
"type": "info"
}
}
},
{
"type": "input",
"group": "password",
"attributes": {
"name": "method",
"type": "submit",
"value": "password",
"disabled": false,
"node_type": "input"
},
"messages": [],
"meta": {
"label": {
"id": 1010001,
"text": "Sign in",
"type": "info",
"context": {}
}
}
}
]
},
"created_at": "2023-03-23T05:16:24.578615Z",
"updated_at": "2023-03-23T05:16:24.578615Z",
"refresh": false,
"requested_aal": "aal1",
"instanceOf": "KratosForm"
}
oauth2_login_challenge
is null
. I'm not sure if it's supposed to return hydra's login_challenge
. A successful login only returns a kratos session cookie, no tokens are returned.
Any assistance would be greatly appreciated.
oauth2_login_challenge
isnull
. I'm not sure if it's supposed to return hydra'slogin_challenge
. A successful login only returns a kratos session cookie, no tokens are returned. Any assistance would be greatly appreciated.
I managed to solve my issues. In kratos.yml
, oauth2_provider.url
needs to be http://hydra:4445
instead of localhost
. Another issue was that my secrets.system
changed since I initialized my postgres db, so I needed to reset the db.
Configure Hydra's authorization authentication, how it should be configured in the profile