Add support for SAML/etc auth#3675
Conversation
|
@timabbott @mateuszmandera I'd like to test this against a server that has SAML auth. How would you recommend doing that? |
|
@gnprice Perhaps Tim will have a better solution to this, but I got something running that can be used now:
|
|
That sounds like a fine way to do the end-to-end SAML test. |
4159ef1 to
71d49a5
Compare
68363a7 to
327acd1
Compare
|
I've now come back to this, and successfully tested it end to end! (With @mateuszmandera 's very helpful test server mentioned above.) So I've cleaned up the branch (commit messages, another test case, tweak some naming and a comment) and it's now ready for review.
|
rk-for-zulip
left a comment
There was a problem hiding this comment.
The first commit message could use a reference to the Zulip server commit (and/or PR) in which the external_authentication_methods field landed.
Other than that, LGTM.
| const externalMethodIcons = new Map([ | ||
| ['google', IconGoogle], | ||
| ['github', IconGitHub], | ||
| ['azuread', IconWindows], | ||
| ]); |
There was a problem hiding this comment.
This information already exists as a slice of the availableExternalMethods table; perhaps it should be extracted from there?
There was a problem hiding this comment.
Could do. As a quick experiment just now, I wrote that and it looks like this:
const externalMethodIcons = new Map(
availableExternalMethods.map(method => [method.name, method.Icon]),
);
Thinking a bit more, though, I think I prefer the version that recites it explicitly. It's true right now that this has the same values as that slice of availableExternalMethods, but:
availableExternalMethodsis the legacy API, and in general I prefer the implementation of a current API to stand alone without depending on the implementation of a legacy API.- Vice versa (legacy depends on current) would be great, but I don't see a trivial way to do that here.
- As more external methods are added in the future that have natural icons to use, we'd like to add them to this list, but
availableExternalMethodswon't grow.
Of these only the first is a particularly overriding reason. So if this were more complicated I probably would want to share it, and would just do so in the other direction: arrange for availableExternalMethods (or its use site) to get the data from here, and say YAGNI to the "more in future" point.
(Well, we probably are going to need more in future; what that really means is more like "we'll cross that bridge when we come to it, and it'll be fine.")
But this is so simple, it doesn't seem worth complicating the code.
| // in, which we don't have to load and can color to match the button. | ||
| // TODO perhaps switch to server's, for the sake of SAML where ours is | ||
| // generic and the server may have a more specific one. | ||
| const Icon = externalMethodIcons.get(method.name) ?? IconPrivate; |
There was a problem hiding this comment.
This seems awkward: the server doesn't actually have to send any particular name or display_name for any particular login_url, so using name in particular to select the icon seems arbitrary.
(I have no constructive suggestions here, unfortunately.)
There was a problem hiding this comment.
This is actually exactly the sort of thing that name is here for 🙂 . As the docs put it:
[...]
name, which is a unique, stable, machine-readable name for the authentication method.
The display name could easily get tweaked in the future, and the login URL certainly has been known to change (see comment about Google auth, above in this file). The name property is here so that when a client has some logic they want to apply to a particular authentication method, there's a reasonable test to hang it off of.
| serverSettings.external_authentication_methods, | ||
| ).map(auth => ( | ||
| <ZulipButton | ||
| key={auth.name} |
There was a problem hiding this comment.
name should be unique; but we need to check it anyway, or else this will have undefined behavior.
(... although on second thought, do we have any use for key here at all?)
There was a problem hiding this comment.
Hmm -- we probably don't! I'll think about that a bit.
If we do keep key, I agree, there should be a check. Thanks for spotting that.
There was a problem hiding this comment.
Yeah, I don't see a point in having key here -- these are just buttons, and have no internal state that could make it relevant to preserve their identities.
On top of which, there's no way for the list of them to change in an update anyway.
Looks like the key prop was added here in 3a279bc, without explanation. I'll just take it out.
There was a problem hiding this comment.
these are just buttons, and have no internal state that could make it relevant to preserve their identities.
As I type this bit into a commit message, I realize it isn't quite true -- if the user has just touched a button so e.g. the Material "ink splash" animation is in progress, that animation state belongs to the button and not to an unrelated button that might appear in the same spot.
... And although it is true that there's no way for the list to change in an update (it comes from a nav param, so it's part of the historical fact of how we navigated here), that feels like a bit of a fragile fact. So now I'm inclined to say that it's good practice to have a key: this is part of a dynamic list, the identity would matter to UI polish if there were insertions or deletions to the list, and it's best not to rely on the more external and fragile fact that the list won't actually change after the component is first rendered.
I'll just add the check that the name is unique, then.
This landed recently in the server, and is expected to be in the upcoming Zulip Server v2.1 release. The server implementation was in zulip/zulip#13307 and some followup PRs, all linked from zulip#3670. The relevant commits appear in the following range: git log --stat -p --author=mateusz 9532e9980^..b05a0d017 The latest of them is 2.1.0-rc1~136 .
In an upcoming commit, we'll start consuming the information from the new external_authentication_methods API. Set that up by separating the part of this logic that will change then from the part that won't.
Tested end-to-end by logging into Mateusz's test production server with Okta over SAML. Fixes: zulip#3670
|
Thanks for the review! Just pushed an update which adds the unique- |
Most of the commits in this branch are just #3674 ; the last few are the part specific to this PR.
This is a draft because I haven't yet had a chance to test it end to end. Barring surprises there, though, I think the code is basically ready.
Fixes #3670 .