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() | load_dotenv() | ||||||
| 
 | 
 | ||||||
| server_port = getenv('SERVER_PORT', '8099') | server_port = getenv('SERVER_PORT', '8099') | ||||||
|  | base_url = getenv('BASE_URL', 'https://demo.cy7.de') | ||||||
| 
 | 
 | ||||||
| app_factory = zope_app_factory | app_factory = zope_app_factory | ||||||
| 
 | 
 | ||||||
|  | @ -19,8 +20,14 @@ dbpassword = getenv('DBPASSWORD', 'secret') | ||||||
| dbschema = getenv('DBSCHEMA', 'demo') | dbschema = getenv('DBSCHEMA', 'demo') | ||||||
| 
 | 
 | ||||||
| # authentication settings | # authentication settings | ||||||
|  | oidc_provider = 'https://a1.cy7.de' | ||||||
|  | oidc_client_id = getenv('OIDC_CLIENT_ID', '311613119816392525') | ||||||
| oidc_params = dict( | oidc_params = dict( | ||||||
|     provider_url=getenv('OIDC_PROVIDER_URL', 'https://a1.cy7.de/oauth/v2/authorize'), |     auth_url=getenv('OIDC_PROVIDER_URL', oidc_provider + '/oauth/v2/authorize'), | ||||||
|     client_id=getenv('OIDC_CLIENT_ID', '311613119816392525'), |     callback_url=getenv('OIDC_CALLBACK_URL', base_url + '/auth/callback'), | ||||||
|     callback_url=getenv('OIDC_CALLBACK_URL', 'https://demo.cy7.de/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 | # 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 oic.oic.message import AuthorizationResponse | ||||||
| 
 | from time import time | ||||||
| from zope.authentication.interfaces import IAuthentication | from zope.authentication.interfaces import IAuthentication | ||||||
| from zope.interface import implementer | from zope.interface import implementer | ||||||
| from zope.publisher.interfaces import Unauthorized | from zope.publisher.interfaces import Unauthorized | ||||||
|  | @ -53,48 +55,79 @@ class Authenticator(DummyFolder): | ||||||
| 
 | 
 | ||||||
|     prefix = 'auth' |     prefix = 'auth' | ||||||
| 
 | 
 | ||||||
|  |     def __init__(self, request): | ||||||
|  |         self.request = request | ||||||
|  |         self.params = config.oidc_params | ||||||
|  | 
 | ||||||
|     def authenticate(request): |     def authenticate(request): | ||||||
|         return None |         return None | ||||||
| 
 | 
 | ||||||
|     def login(self, request): |     def login(self): | ||||||
|         params = config.oidc_params |         req = self.request | ||||||
|         print('*** login', self, request.getTraversalStack(), request['PATH_INFO']) |         print('*** login', self, req.getTraversalStack(), req['PATH_INFO']) | ||||||
|         #print('***', dir(request)) |         #print('***', dir(req)) | ||||||
|         client = oic.Client() |         client = oic.Client() | ||||||
|         #providerInfo = client.provider_config(params['provider_url']) |         #providerInfo = client.provider_config(params['provider_url']) | ||||||
|         #print('***', providerInfo) |         #print('***', providerInfo) | ||||||
|         #client.register(providerInfo['registration_endpoint'], application_type='web') |         state = rndstr() | ||||||
|         requestArgs = dict( |         nonce = rndstr() | ||||||
|                 client_id=params['client_id'], |         args = dict( | ||||||
|  |                 client_id=self.params['client_id'], | ||||||
|                 response_type='code', # 'code id_token token', |                 response_type='code', # 'code id_token token', | ||||||
|                 state=rndstr(), nonce=rndstr(), |                 state=state, nonce=nonce, | ||||||
|                 scope=['openid', 'profile'], |                 scope=['openid', 'profile'], | ||||||
|                 redirect_uri=params['callback_url'], |                 redirect_uri=self.params['callback_url'], | ||||||
|         ) |         ) | ||||||
|         authReq = client.construct_AuthorizationRequest(request_args=requestArgs) |         addArgs, codeVerifyer = client.add_code_challenge() | ||||||
|         #loginUrl = authReq.request(client.authorization_endpoint) |         args.update(addArgs) | ||||||
|         loginUrl = authReq.request(params['provider_url']) |         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) |         print('***', loginUrl) | ||||||
|         request.response.redirect(loginUrl, trusted=True) |         req.response.redirect(loginUrl, trusted=True) | ||||||
| 
 | 
 | ||||||
|     def callback(self, request): |     def callback(self): | ||||||
|         print('*** callback', self, request.form) |         req = self.request | ||||||
|         code = request.form['code'] |         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) | @register('auth', Root) | ||||||
| def authView(context, request): | def authView(context, request): | ||||||
|     print('*** auth', context, request['PATH_INFO']) |     print('*** auth', context, request['PATH_INFO']) | ||||||
|     return Authenticator() |     return Authenticator(request) | ||||||
| 
 | 
 | ||||||
| @register('login', Authenticator) | @register('login', Authenticator) | ||||||
| def login(context, request): | def login(context, request): | ||||||
|     context.login(request) |     context.login() | ||||||
|     return DefaultView(context, request) |     return DefaultView(context, request) | ||||||
| 
 | 
 | ||||||
| @register('callback', Authenticator) | @register('callback', Authenticator) | ||||||
| def callback(context, request): | def callback(context, request): | ||||||
|     context.callback(request) |     context.callback() | ||||||
|     return DefaultView(context, request) |     return DefaultView(context, request) | ||||||
| 
 | 
 | ||||||
| @register('logout', Authenticator) | @register('logout', Authenticator) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue