-
Notifications
You must be signed in to change notification settings - Fork 1.1k
oidc: Google JWKS/services scaffolding #13569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
Needs tests and other work, but the basic structure here is good for an initial review! |
Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
This is getting a little bit unwieldy and duplicative -- given that we're likely going to add a third issuer soon, I think we should find a way to simplify this. One thought is that we could a) have a lookup table that maps from (issuer, pending) -> publisher_classes = {
GITHUB_OIDC_ISSUER_URL: [GitHubPublisher, PendingGitHubPublisher],
GOOGLE_OIDC_ISSUER_URL: [GooglePublisher, PendingGooglePublisher],
}
def find_publisher_by_issuer(session, issuer_url, signed_claims, *, pending=False):
try:
publisher_cls = publisher_classes[issuer_url][pending]
except KeyError:
return None
# Check for a publisher with options
publisher = (
session.query(publisher_cls)
.filter_by(publisher_cls.filter_expr_with_options(signed_claims))
.one_or_none()
)
# Check for a fallback publisher
return (
session.query(publisher_cls)
.filter_by(publisher_cls.filter_expr_without_options(signed_claims))
.one_or_none()
) |
That sounds good to me! The class mapping part is certainly doable; storing the expressions might be slightly trickier (since e.g. the Do you want me to look into that with this PR, or hold off until the next round of publishers (e.g. GitLab)? |
I think I'd like to try to do it here, maybe take a crack at it and see how much of a time suck it'll be? Fine with me if you think it's not worth the effort though! |
Let's find out 🙂 |
One thought: how should this work if/when we have publishers with multiple optional claims? It should be fine if we don't include multiple optionals in the unique constraint set, but if we do it'll probably result in This doesn't solve that problem, but in terms of devolving it: for lookup in publisher_cls.lookups:
if publisher := session.query(publisher_cls).filter(lookup(signed_claims)):
return publisher (Where |
Maybe premature optimization? But I think a list of N!+1 increasingly loosened filter expressions would also satisfy the current two-query case as well, so might be worth doing. The alternative would be writing N!+1 queries, so I don't think there's any way around the general behavior here. |
Actually, thinking about it some more: these don't even need to be written out manually (which would be error-prone), since they're expressible via the existing I'll play around with that a bit 🙂 |
This devolves the lookup logic for each publisher type back to its actual class (or base mixin, as appropriate). The downside is that it's a little magical: each OIDCPublisher now provides __lookup_strategies__, which is a list of callables that resolve a model type and a claim set into an optional query, which can then be realized with a DB session into exactly one or none publishers. Signed-off-by: William Woodruff <[email protected]> tests: update tests Signed-off-by: William Woodruff <[email protected]>
059b1e6 is my attempt at this: the lookup logic is now devolved back to each publisher (or more accurately, the "base" mixin between pending and non-pending publishers of each type). Each publisher type now supplies A bit of nastiness happens with these callables: conceptually they're |
…vices Signed-off-by: William Woodruff <[email protected]>
Signed-off-by: William Woodruff <[email protected]>
This should be good to go again. |
WIP.This also needs some more changes, but I'll wait for #13566 to make them.
See #13551.