oidc auth: improvements, store info in cookie
This commit is contained in:
		
							parent
							
								
									0207d12b46
								
							
						
					
					
						commit
						c1f07effee
					
				
					 2 changed files with 64 additions and 24 deletions
				
			
		|  | @ -7,6 +7,7 @@ from scopes.server.app import zope_app_factory | |||
| load_dotenv() | ||||
| 
 | ||||
| server_port = getenv('SERVER_PORT', '8099') | ||||
| base_url = getenv('BASE_URL', 'https://demo.cy7.de') | ||||
| 
 | ||||
| app_factory = zope_app_factory | ||||
| 
 | ||||
|  | @ -19,8 +20,14 @@ dbpassword = getenv('DBPASSWORD', 'secret') | |||
| dbschema = getenv('DBSCHEMA', 'demo') | ||||
| 
 | ||||
| # authentication settings | ||||
| oidc_provider = 'https://a1.cy7.de' | ||||
| oidc_client_id = getenv('OIDC_CLIENT_ID', '311613119816392525') | ||||
| oidc_params = dict( | ||||
|     provider_url=getenv('OIDC_PROVIDER_URL', 'https://a1.cy7.de/oauth/v2/authorize'), | ||||
|     client_id=getenv('OIDC_CLIENT_ID', '311613119816392525'), | ||||
|     callback_url=getenv('OIDC_CALLBACK_URL', 'https://demo.cy7.de/auth/callback'), | ||||
|     auth_url=getenv('OIDC_PROVIDER_URL', oidc_provider + '/oauth/v2/authorize'), | ||||
|     callback_url=getenv('OIDC_CALLBACK_URL', base_url + '/auth/callback'), | ||||
|     client_id = oidc_client_id, | ||||
|     cookie_name=getenv('OIDC_COOKIE_NAME', 'oidc_' + oidc_client_id), | ||||
|     cookie_domain=getenv('OIDC_COOKIE_DOMAIN', 'cy7.de'), | ||||
|     cookie_lifetime=getenv('OIDC_COOKIE_LIFETIME', '86400'), | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,8 +1,10 @@ | |||
| # scopes.server.auth | ||||
| 
 | ||||
| from oic import oic, rndstr | ||||
| from email.utils import formatdate | ||||
| import json | ||||
| from oic import oic, rndstr, unreserved | ||||
| from oic.oic.message import AuthorizationResponse | ||||
| 
 | ||||
| from time import time | ||||
| from zope.authentication.interfaces import IAuthentication | ||||
| from zope.interface import implementer | ||||
| from zope.publisher.interfaces import Unauthorized | ||||
|  | @ -53,48 +55,79 @@ class Authenticator(DummyFolder): | |||
| 
 | ||||
|     prefix = 'auth' | ||||
| 
 | ||||
|     def __init__(self, request): | ||||
|         self.request = request | ||||
|         self.params = config.oidc_params | ||||
| 
 | ||||
|     def authenticate(request): | ||||
|         return None | ||||
| 
 | ||||
|     def login(self, request): | ||||
|         params = config.oidc_params | ||||
|         print('*** login', self, request.getTraversalStack(), request['PATH_INFO']) | ||||
|         #print('***', dir(request)) | ||||
|     def login(self): | ||||
|         req = self.request | ||||
|         print('*** login', self, req.getTraversalStack(), req['PATH_INFO']) | ||||
|         #print('***', dir(req)) | ||||
|         client = oic.Client() | ||||
|         #providerInfo = client.provider_config(params['provider_url']) | ||||
|         #print('***', providerInfo) | ||||
|         #client.register(providerInfo['registration_endpoint'], application_type='web') | ||||
|         requestArgs = dict( | ||||
|                 client_id=params['client_id'], | ||||
|         state = rndstr() | ||||
|         nonce = rndstr() | ||||
|         args = dict( | ||||
|                 client_id=self.params['client_id'], | ||||
|                 response_type='code', # 'code id_token token', | ||||
|                 state=rndstr(), nonce=rndstr(), | ||||
|                 state=state, nonce=nonce, | ||||
|                 scope=['openid', 'profile'], | ||||
|                 redirect_uri=params['callback_url'], | ||||
|                 redirect_uri=self.params['callback_url'], | ||||
|         ) | ||||
|         authReq = client.construct_AuthorizationRequest(request_args=requestArgs) | ||||
|         #loginUrl = authReq.request(client.authorization_endpoint) | ||||
|         loginUrl = authReq.request(params['provider_url']) | ||||
|         addArgs, codeVerifyer = client.add_code_challenge() | ||||
|         args.update(addArgs) | ||||
|         self.storeSession(dict(state=state, nonce=nonce, codeVerifyer=codeVerifyer)) | ||||
|         authReq = client.construct_AuthorizationRequest(request_args=args) | ||||
|         loginUrl = authReq.request(self.params['auth_url']) | ||||
|         print('***', loginUrl) | ||||
|         request.response.redirect(loginUrl, trusted=True) | ||||
|         req.response.redirect(loginUrl, trusted=True) | ||||
| 
 | ||||
|     def callback(self, request): | ||||
|         print('*** callback', self, request.form) | ||||
|         code = request.form['code'] | ||||
|     def callback(self): | ||||
|         req = self.request | ||||
|         print('*** callback', self, req.form) | ||||
|         data = self.loadSession() | ||||
|         code = req.form['code'] | ||||
|         client = oic.Client() | ||||
|         print('***', data, code, client) | ||||
| 
 | ||||
|     def storeSession(self, data): | ||||
|         options = {} | ||||
|         lifetime = int(self.params['cookie_lifetime']) | ||||
|         options['expires'] = formatdate(time() + lifetime, localtime=False, usegmt=True) | ||||
|         options['max-age'] = lifetime | ||||
|         domain = self.params['cookie_domain'] | ||||
|         if domain: | ||||
|             options['domain'] = domain | ||||
|         #options['httponly'] = True | ||||
|         name = self.params['cookie_name'] | ||||
|         value = json.dumps(data) | ||||
|         self.request.response.setCookie(name, value, **options) | ||||
| 
 | ||||
|     def loadSession(self): | ||||
|         cookie = self.request.getCookies().get(self.params['cookie_name']) | ||||
|         if cookie is None: | ||||
|             raise ValueError('Missing authentication cookie') | ||||
|         data = json.loads(cookie) | ||||
|         return data | ||||
| 
 | ||||
| 
 | ||||
| @register('auth', Root) | ||||
| def authView(context, request): | ||||
|     print('*** auth', context, request['PATH_INFO']) | ||||
|     return Authenticator() | ||||
|     return Authenticator(request) | ||||
| 
 | ||||
| @register('login', Authenticator) | ||||
| def login(context, request): | ||||
|     context.login(request) | ||||
|     context.login() | ||||
|     return DefaultView(context, request) | ||||
| 
 | ||||
| @register('callback', Authenticator) | ||||
| def callback(context, request): | ||||
|     context.callback(request) | ||||
|     context.callback() | ||||
|     return DefaultView(context, request) | ||||
| 
 | ||||
| @register('logout', Authenticator) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue