Auth0 SSO/SAML Integration with CLI - #245
Conversation
Codecov Report
@@ Coverage Diff @@
## master #245 +/- ##
=========================================
Coverage ? 40.28%
=========================================
Files ? 61
Lines ? 4629
Branches ? 0
=========================================
Hits ? 1865
Misses ? 2523
Partials ? 241
Continue to review full report at Codecov.
|
Cody A. Ray (codyaray)
left a comment
There was a problem hiding this comment.
auth code with pkce looks like the right flow for me, for now. i bet we could get a nicer "success" page, but this works for v1 anyway.
my main concerns
-
we're opening a small security hole here that i think our auditors will dislike, in that the new check_email endpoint allows users to query whether emails exist directly. we were already flagged for giving too much info away like this at authentication time by them once or twice. Instead, can we have the user indicate whether they want to "login via SSO" with a new command or flag?
-
we're exposing auth0 externally as part of our API and hardcoding a lot of API details into our CLI that shouldn't be there. We should really setup a proxy for a lot of this stuff (so instead of https://confluent.auth0.com/api/v2/authorize it looks like https://confluent.cloud/oauth/authorize). I think both Apache webserver and Nginx support this sort of proxying, or something like https://github.com/trondhindenes/Auth0Proxy (which configures apache in a docker container)
| // Check if user has an enterprise SSO connection enabled. If so we need to start | ||
| // a background HTTP server to support the authorization code flow with PKCE | ||
| // described at https://auth0.com/docs/flows/guides/auth-code-pkce/call-api-auth-code-pkce | ||
| userSSO, err := client.User.CheckEmail(context.Background(), &orgv1.User{Email: email}) |
There was a problem hiding this comment.
CheckEmail is like GetUserByEmail? And userSSO is just our normal ccloudapis User object?
This is a security hole, since it exposes an easy method for attackers to figure out which emails exist in our system without authenticating.
There was a problem hiding this comment.
Yes, except all the returned User object contains (if non-empty) is the email and sso field (everything else is blanked out).
The GUI also has always had the same "vulnerability" according to when I talked to FE team. cc laura-brouckman . So this is not an additional security hole, if you'd even consider it one.
And unfortunately there is no better way to do this without compromising the UX :(
We could consider not returning the email in the returned User object from the route, that might make it a bit more secure? So it's just sso or (no sso) or (no sso because invalid)? Wdyt?
There was a problem hiding this comment.
This should not make it obvious when a user exists or not.
Suggested output
(Nesting it inside "user" means it should be backwards compatible with the current GetUserReply-based output)
Exists with SSO:
200 OK HTTP/1.1
{
"user": {
"sso": {
"enabled": true,
"auth0_connection_name": "noah-okta-test"
}
}
}
Exists without SSO:
200 OK HTTP/1.1
{
"user": {
"sso": {
"enabled": false,
"auth0_connection_name": ""
}
}
}
Doesn't exist (identical to exists without SSO):
200 OK HTTP/1.1
{
"user": {
"sso": {
"enabled": false,
"auth0_connection_name": ""
}
}
}
Current Behavior
Exists with SSO
{
"user": {
"id": 0,
"email": "david.hyde@confluent.io",
"first_name": "",
"last_name": "",
"organization_id": 0,
"deactivated": false,
"verified": null,
"created": null,
"modified": null,
"password_changed": null,
"service_name": "",
"service_description": "",
"service_account": false,
"sso": {
"enabled": true,
"auth0_connection_name": "noah-okta-test"
}
},
"account": null,
"organization": null,
"error": null,
"accounts": []
}
Exists without SSO:
{
"user": {
"id": 0,
"email": "cody@confluent.io",
"first_name": "",
"last_name": "",
"organization_id": 0,
"deactivated": false,
"verified": null,
"created": null,
"modified": null,
"password_changed": null,
"service_name": "",
"service_description": "",
"service_account": false,
"sso": {
"enabled": false,
"auth0_connection_name": ""
}
},
"account": null,
"organization": null,
"error": null,
"accounts": []
}
Not exists
{
"user": null,
"account": null,
"organization": null,
"error": {
"code": 404,
"message": "User not found",
"nested_errors": {},
"details": [],
"stack": null
},
"accounts": []
}
There was a problem hiding this comment.
Yes, we will do this as a follow up PR in cc-gateway-service (should require no changes in CLI).
|
Cody A. Ray (@codyaray) yeah I'm going to spruce up the success page a bit before merging. css! |
|
To your point #2, that URL is actually an ID, not the hostname we connect to. And I think it's provided by Auth0, I don't think we can change that. cc Eric Sirianni (@sirianni) |
| // Check if user has an enterprise SSO connection enabled. If so we need to start | ||
| // a background HTTP server to support the authorization code flow with PKCE | ||
| // described at https://auth0.com/docs/flows/guides/auth-code-pkce/call-api-auth-code-pkce | ||
| userSSO, err := client.User.CheckEmail(context.Background(), &orgv1.User{Email: email}) |
There was a problem hiding this comment.
This should not make it obvious when a user exists or not.
Suggested output
(Nesting it inside "user" means it should be backwards compatible with the current GetUserReply-based output)
Exists with SSO:
200 OK HTTP/1.1
{
"user": {
"sso": {
"enabled": true,
"auth0_connection_name": "noah-okta-test"
}
}
}
Exists without SSO:
200 OK HTTP/1.1
{
"user": {
"sso": {
"enabled": false,
"auth0_connection_name": ""
}
}
}
Doesn't exist (identical to exists without SSO):
200 OK HTTP/1.1
{
"user": {
"sso": {
"enabled": false,
"auth0_connection_name": ""
}
}
}
Current Behavior
Exists with SSO
{
"user": {
"id": 0,
"email": "david.hyde@confluent.io",
"first_name": "",
"last_name": "",
"organization_id": 0,
"deactivated": false,
"verified": null,
"created": null,
"modified": null,
"password_changed": null,
"service_name": "",
"service_description": "",
"service_account": false,
"sso": {
"enabled": true,
"auth0_connection_name": "noah-okta-test"
}
},
"account": null,
"organization": null,
"error": null,
"accounts": []
}
Exists without SSO:
{
"user": {
"id": 0,
"email": "cody@confluent.io",
"first_name": "",
"last_name": "",
"organization_id": 0,
"deactivated": false,
"verified": null,
"created": null,
"modified": null,
"password_changed": null,
"service_name": "",
"service_description": "",
"service_account": false,
"sso": {
"enabled": false,
"auth0_connection_name": ""
}
},
"account": null,
"organization": null,
"error": null,
"accounts": []
}
Not exists
{
"user": null,
"account": null,
"organization": null,
"error": {
"code": 404,
"message": "User not found",
"nested_errors": {},
"details": [],
"stack": null
},
"accounts": []
}
Cody A. Ray (codyaray)
left a comment
There was a problem hiding this comment.
aside from my earlier comments lgtm
- you're going to update the backend check_email so it doesn't show if user/email exists or not
- you're adding a prettier/auto-closing page in the CLI's http server
- we're stuck with the auth0 identifier
- you'll update the Auth0ConnectionName in cc-structs and json field, but will have to deprecate it at this point and wait until we know no one would be using it to remove it.
I'm not following this one ☝️ |

No description provided.