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.

Reply via email to