QuicknDirty How-To for SSO between web2py and py4web with KeyCloak

292 views
Skip to first unread message

Kevin Keller

unread,
Aug 31, 2020, 1:53:41 PM8/31/20
to py4web, web2py-users
In web2py put this in your db.py:

# Define oauth application id and secret.
Kcloak_CLIENT_ID='XXXX'
Kcloak_CLIENT_SECRET="XXXXX"

## import required modules
try:
    import json
except ImportError:
    from gluon.contrib import simplejson as json
from gluon.contrib.login_methods.oauth20_account import OAuthAccount

## extend the OAUthAccount class
class KCloakAccount(OAuthAccount):
#    """OAuth impl for KeyCloak"""
    AUTH_URL="http(s)://KEYCLOAKIPANDPORT/auth/realms/master/protocol/openid-connect/auth"
    TOKEN_URL="http(s)://KEYCLOAKIPANDPORT/auth/realms/master/protocol/openid-connect/token"

    def __init__(self):
           OAuthAccount.__init__(self, None, Kcloak_CLIENT_ID, Kcloak_CLIENT_SECRET,
                              self.AUTH_URL, self.TOKEN_URL,
                              scope='openid profile email',
                              state="klcoak",
                              display='popup')


    def get_user(self):

        if not self.accessToken():
            return None
       #global token
        token= None
        token=self.accessToken()
        print (token)
        #from okta_jwt.jwt import validate_token
        issuer="http(s)://KEYCLOAKIPANDPORT/auth/realms/master"
        audience="http(s)://YOURWEB2PYPAGEURL"
        import jwt
        profile=jwt.decode(token,verify=False)
        if profile['sub']:
                 username = profile['email']
                 email = profile['email']
                 first_name = profile['given_name']
                 last_name = profile['family_name']
                 return dict(username = username, first_name=first_name,last_name=last_name,email = '%s' %(email))
         
           
        else:
              self.session.token = None

and put this in your 

gluon/contrib/login_methods/oauth20_account.py

replace whatever you have under the logout function with: 

del current.session.token
        del current.session.auth
        current.session.token = None
        current.session.auth = None
        redirect('http(s)://KEYCLOAKIPPORT/auth/realms/master/protocol/openid-connect/logout?redirect_uri=*ENCODEDURLTOREDIRECTAFTERLOGOUT" ')


End Web2py part. 


For py4web: 

Create oauth2keycloak.py file in py4web/utils/auth_plugins/ and put in this:


from . import OAuth2


class OAuth2Keycloak(OAuth2):
    name = "oauth2keycloak"
    login_url = "http(s)://KEYCLOAKIPPORT/auth/realms/master/protocol/openid-connect/auth"
    token_url = "http(s)://KEYCLOAKIPPORT/auth/realms/master/protocol/openid-connect/token"
    userinfo_url = "http(s)://KEYCLOAKIPPORT/auth/realms/master/protocol/openid-connect/userinfo"
    revoke_url = "http(s)://KEYCLOAKIPPORT/auth/realms/master/protocol/openid-connect/logout"
    default_scope = "openid profile"
    maps = {
        "username": "email",
        "email":"email",
        "sso_id": "email",
        "first_name": "given_name",
        "last_name": "family_name",
    }


In your app (probably based on scaffold) go to your static/components/auth.html and add a button for KeyCloak: 

<a v-if="plugins.indexOf('oauth2keycloak')>=0"
class="button is-link"
v-bind:href="'../auth/plugin/oauth2keycloak/login?next='+next">Login with KeyCloak</a>

Also in your scaffoled app add the plugin to the auth.html file under templates: 

<div class="column is-half is-offset-one-quarter" style="border : 1px solid #e1e1e1; border-radius: 10px">
      <auth plugins="local,oauth2keycloak"></auth>


Finally for single logout add this line to your logout function in py4web/utils/auth.py

526         elif path == "logout":                                                  
527             self.session.clear()                                                                              
528             redirect ('http(s)://KEYCLOAKIPPORT/auth/realms/master/protocol/openid-connect/logout?redirect_uri=*ENCODEDREDIRECTURIAFTERLOGOUT*

Of course you need to install keycloak and create 2 openid clients with secrets. 

Thats it in a nutshell. 







Reply all
Reply to author
Forward
0 new messages