I am working on an internal deployment of Binderhub and attempting to get auth working using Okta as the identity provider. I have successfully deployed Binderhub without auth but running into issues when enabling auth. After the user logs in there are a series of redirects ultimately ending in a “400 : Bad Request. OAuth state missing from cookies” error.
The request chain is as follows:
https://binderhub-aegean.hubs.ginkgo.zone/
This is url for the main binderhub frontend that has the form to help create a new binder link.
-
https://binder-aegean.hubs.ginkgo.zone/hub/api/oauth2/authorize?client_id=service-binderhub&redirect_uri=https%3A%2F%2Fbinder-aegean.hubs.ginkgo.zone%2Fhub%2Foauth_callback&response_type=code&state=eyJ1dWlkIjogIjE2NWIyMzcwNWJkZDQ0NDRiMTBiYTYwZjZlZjg3NDdmIiwgIm5leHRfdXJsIjogIi8ifQ
-
https://binder-aegean.hubs.ginkgo.zone/hub/login?next=%2Fhub%2Fapi%2Foauth2%2Fauthorize%3Fclient_id%3Dservice-binderhub%26redirect_uri%3Dhttps%253A%252F%252Fbinder-aegean.hubs.ginkgo.zone%252Fhub%252Foauth_callback%26response_type%3Dcode%26state%3DeyJ1dWlkIjogIjE2NWIyMzcwNWJkZDQ0NDRiMTBiYTYwZjZlZjg3NDdmIiwgIm5leHRfdXJsIjogIi8ifQ
At this point the user is shown a “Sign in with OAuth 2.0” button. CLicking this then goes to
-
https://binder-aegean.hubs.ginkgo.zone/hub/oauth_login?next=%2Fhub%2Fapi%2Foauth2%2Fauthorize%3Fclient_id%3Dservice-binderhub%26redirect_uri%3Dhttps%253A%252F%252Fbinder-aegean.hubs.ginkgo.zone%252Fhub%252Foauth_callback%26response_type%3Dcode%26state%3DeyJ1dWlkIjogIjE2NWIyMzcwNWJkZDQ0NDRiMTBiYTYwZjZlZjg3NDdmIiwgIm5leHRfdXJsIjogIi8ifQ
-
https://ginkgobioworks.okta.com/oauth2/v1/authorize?response_type=code&redirect_uri=https%3A%2F%2Fbinder-aegean.hubs.ginkgo.zone%2Fhub%2Foauth_callback&client_id=0oa1zwkihh4w6HN1t0h8&state=eyJzdGF0ZV9pZCI6ICI3MTkyYzY1YmNmYTQ0M2M3OTI3MGExMjc1YjM5ZmE1NSJ9&scope=openid+email+profile
User is prompted to enter their Okta credentials. Putting this in and clicking “Sign In” then redirects to:
-
https://ginkgobioworks.okta.com/login/token/redirect?stateToken=02.id.U7pU2DRp8Y2DekJDYaai-91Jm1GX5IOQMQ0025av
-
https://binder-aegean.hubs.ginkgo.zone/hub/oauth_callback?code=4P-0axeqZMxv9C2XW44tXlAsjlvMWxF86759dggAFJE&state=eyJzdGF0ZV9pZCI6ICI3MTkyYzY1YmNmYTQ0M2M3OTI3MGExMjc1YjM5ZmE1NSJ9
-
https://binder-aegean.hubs.ginkgo.zone/hub/api/oauth2/authorize?client_id=service-binderhub&redirect_uri=https%3A%2F%2Fbinder-aegean.hubs.ginkgo.zone%2Fhub%2Foauth_callback&response_type=code&state=eyJ1dWlkIjogIjE2NWIyMzcwNWJkZDQ0NDRiMTBiYTYwZjZlZjg3NDdmIiwgIm5leHRfdXJsIjogIi8ifQ
-
https://binder-aegean.hubs.ginkgo.zone/hub/oauth_callback?code=wtyRnRNcykKk8iTKHBl2QaluSssF6a&state=eyJ1dWlkIjogIjE2NWIyMzcwNWJkZDQ0NDRiMTBiYTYwZjZlZjg3NDdmIiwgIm5leHRfdXJsIjogIi8ifQ
At this last page is where we see the 400 error. At step #8 when looking at the cookies, there is a request for oauthenticator-state
however the response for that cookie is an empty value “”.
Note that binderhub-aegean is the domain for binderhub and binder-aegean is the domain for the hub.
I am able to click “home” from this error page which takes me to
https://binder-aegean.hubs.ginkgo.zone/hub/home
and here I can click “Start My Server” and successfully spawns a new Jupyter server pod. So it seems like auth is partially working at least for the jupyterhub piece but I’m not able to get to the main Binderhub page to create links. I have also attempted to hand make a Binderhub link and use that however I get the same error.
We use kr8 and flux to manage our third party k8s applications. Components in kr8 are defined in jsonnet which then gets merged with the base helm-chart to create the final manifst which flux then applies. This is a truncated version of the kr8 config for the auth enabled binderhub.
{
config: {
BinderHub: {
hub_url: 'https://binder-aegean.hubs.ginkgo.zone/',
image_prefix: 'artifactory.releng.ginkgo.zone/docker/binderhub/',
use_registry: true,
build_token_secret: '<secret>>', // secret needs to be in hex
auth_enabled: true,
},
jupyterhub: {
hub: {
existingSecret: 'hub-secret',
config: {
BinderSpawner: {
auth_enabled: true,
},
JupyterHub: {
redirect_to_server: false,
authenticator_class: 'generic-oauth',
},
GenericOAuthenticator: {
allow_all: true,
oauth_callback_url: config.hub_url + 'hub/oauth_callback',
authorize_url: 'https://ginkgobioworks.okta.com/oauth2/v1/authorize',
token_url: 'https://ginkgobioworks.okta.com/oauth2/v1/token',
userdata_url: 'https://ginkgobioworks.okta.com/oauth2/v1/userinfo',
username_claim: 'email',
enable_auth_state: true,
scope: [
'openid',
'email',
'profile',
],
},
},
cookieSecret: '<secret>>',
services: {
binder: {
oauth_client_id: 'service-binderhub',
oauth_no_confirm: true,
oauth_redirect_uri: config.hub_url + 'hub/oauth_callback',
apiToken: '<secret>',
},
loadRoles: {
user: {
scopes: ['self', 'access:services!service=binder'],
},
},
},
proxy: {
secretToken: '<secret>',
service: {
type: 'ClusterIP',
},
},
singleuser: {
cmd: 'jupyterhub-singleuser',
cloudMetadata: {
blockWithIptables: false,
ip: '<secret>>',
},
},
},
},
},
}
Within the Okta configuration I have set
Sign-in redirect URIs:
https://binderhub-aegean.hubs.ginkgo.zone/hub/oauth_callback
https://binder-aegean.hubs.ginkgo.zone/hub/oauth_callback
https://binder-aegean.hubs.ginkgo.zone/oauth_callback
Sign-out redirect URIs:
https://binderhub-aegean.hubs.ginkgo.zone
Login flow: "Redirect to app to initiate login (OIDC Compliant)
Initiate login URI:
https://binderhub-aegean.hubs.ginkgo.zone/hub/oauth_callback
I don’t have full understanding of what each setting does and how the auth flow is supposed to work, I’ve just been following the example docs and what I’ve found in forum posts. Any help would be much appreciated!