On Tuesday, May 21, 2019 at 8:13:11 PM UTC-4, Mike Orr wrote: > > > I want it to do username/password checking and give me the user > metadata including the list of roles. Then I can do authorization from > the roles. By "no authorization" I mean the role/view ACLs would > remain in Pyramid; I don't want to put them into Keycloak and ask it > every page view whether this user has permission to this view.
.... > Yes, that's what's so complicated, trying to figure out which classes > I need. I'm trying to implement the "Web Application Flow" in the > 'requests-oauthlib' docs. So I would redirect to Keycloak, and it > would authenticate the user and redirect back. I'm not sure what > exactly to do after that. Keycloak would manage the user's account, > password, whether the user can access this application, and a list of > roles related to the application. > Okay. Within the realm of oAuth and Identity Management, Keycloak is handling Authentication of the user and your Pyramid App will be delegating Authorization to it. Everything else you're talking about in regards to "Authorization" and interpreting the ACLs is within Pyramid and a slightly different concept of Authorization. In terms of oAuth... Pyramid is a client and using Keycloak for Authorization, even though it seems like you're using it for Authentication. Let me talk about a few things you brought up of order, and then try to answer some questions while I leave you with more... Authorization Headers This is fully compatible with Pyramid, don't worry. The oAuth specs prefer/suggest/request that certain oAuth information is exchanged within request headers and not within query strings or post data. This data exchange generally happens between different servers and is implemented by the oauth client (likely requests-oauthlib) or the upstream authority server. It's an implementation detail that is really unrelated to your usage. IIRC, the two places this happens are in the post-authorization redirect from the Authority to your Callback URL and then again in a backend request from your server to the Authority. oAuth Flows and Grants Forget about classes in libraries and just focus on the Spec/Use-Case. I'm pretty sure you want the standard Authorization Code grant, but just to be sure here If you search "oauth flows", you'll see a bunch of blogs and resources describing the different grants and flows. Some of the things you wrote about sound like the legacy Resource Owner Password Credentials flow; if that's what you're trying to do... i suggest you take another look at the Authorization Code flow * https://nordicapis.com/8-types-of-oauth-flows-and-powers/ * https://oauth.net/2/ * https://auth0.com/docs/api-auth/which-oauth-flow-to-use * https://medium.com/@darutk/diagrams-and-movies-of-all-the-oauth-2-0-flows-194f3c3ade85 * https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html Let me explain a bit of the Authorization Code Grant using my library, because that sounds like what you should be doing (that flow, not my library)... 1. The user visits your Application, and is redirected to the Authority with a payload which contains the application id, a random id, a set of credentials to authorize, what they want, and callback URL that you already configured as valid with the authority. At the Authority, they will either login or be logged in, and Authorize the grant. This Pyramid view is a user being redirected from your application: https://github.com/jvanasco/pyramid_oauthlib_lowlevel/blob/master/pyramid_oauthlib_lowlevel/tests/oauth2_app/views.py#L654-L671 2. At the Authority, they generate a temporary oAuth Grant Token to track the authorization and redirect the user to a predetermined callback page on your application. There is some oAuth information in the headers of the redirect. This is the user at the Authority view- https://github.com/jvanasco/pyramid_oauthlib_lowlevel/blob/master/pyramid_oauthlib_lowlevel/tests/oauth2_app/views.py#L178-L241 The GET params on the request to the authority will have a clientId (your app), a redirect url (which must match the one in their database) and a 'state' nonce/session The authority allows the Authenticated user to Authorize the credentials request request, create a session on their side, then redirect to your page. 3. Your application processes the oAuth information contained in the headers on the callback page, and then (4) redirects to a success page or the page originally requested. A library will handle processing all this stuff for you, you should just be pulling the information from validated request via the library's API. This is where that happens https://github.com/jvanasco/pyramid_oauthlib_lowlevel/blob/master/pyramid_oauthlib_lowlevel/tests/oauth2_app/views.py#L673-L724 While this is going on, there are some behind the scenes communications between your server and the Authority. Within Step3, your application will make a request behind-the-scenes to the authority with the information from the callback. The authority will generate a "Server Bearer Token" on their side, and send you a payload with the "Client Bearer Token", which you save on your side and associate with the user in the session. At this point, the "Grant Token" should cease to exists, and both the client (your app) and the authority server will now have a stored "BearerToken". Generally speaking, once someone makes an oAuth authorization for your application to the Identity authority, the authority should pick up a subsequent request and just redirect to the callback and use the existing BearerToken -- instead of asking them to authorize again. Some authorities work differently though. The authorized BearerTokens are generally time-limited and provided with two components - an "Access Token" and a "Refresh Token". The Access Token is a secret string you make all your various requests with and has the expiry time limit; the Refresh Token is a different secret string you use to obtain a new token. If you control both servers, you may not want to time-limit them. After you complete the oAuth grant, you can use the stored token to make automated queries against the upstream server's API to update the user's profile information, ensure they are still registered, etc. The openid connect stuff basically bootstraps a bunch of profile information into the callback payloads. While that is useful, it's generally a one-time data transfer (unless there is some way to resync data), and having the oAuth token is preferred. I hope this quick overview makes sense. ---- In terms of the issue you experienced There are MANY things that can be happening there. two possible ones are: 1. if you are already logged into that service and have already authenticated once on their end, they may be redirecting you to their homepage 2. you may be missing some arguments or you supplied some invalid values in your request, and there is no proper error messaging on the server. I would drop in some `pdb.set_trace()` lines in this console script, and inspect the request objects to see if you have any redirects going on. -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discuss+unsubscr...@googlegroups.com. To post to this group, send email to pylons-discuss@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/72f461ec-f1ad-4930-b0f2-52f661be9b79%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.