auth: get OIDC provider URIs, endpoints, and keys from OP config URLs
This commit is contained in:
		
							parent
							
								
									96afb631e0
								
							
						
					
					
						commit
						f21910e675
					
				
					 3 changed files with 32 additions and 12 deletions
				
			
		|  | @ -31,9 +31,9 @@ dbschema = getenv('DBSCHEMA', 'demo') | ||||||
| oidc_provider = 'https://a1.cy7.de' | oidc_provider = 'https://a1.cy7.de' | ||||||
| oidc_client_id = getenv('OIDC_CLIENT_ID', '311613119816392525') | oidc_client_id = getenv('OIDC_CLIENT_ID', '311613119816392525') | ||||||
| oidc_params = dict( | oidc_params = dict( | ||||||
|     auth_url=getenv('OIDC_PROVIDER_URL', oidc_provider + '/oauth/v2/authorize'), |     op_config_url=oidc_provider + '/.well-known/openid-configuration', | ||||||
|     token_url=getenv('OIDC_TOKEN_URL', oidc_provider + '/oauth/v2/token'), |     op_uris=None, | ||||||
|     userinfo_url=getenv('OIDC_USERINFO_URL', oidc_provider + '/oidc/v1/userinfo'), |     op_keys=None, | ||||||
|     callback_url=getenv('OIDC_CALLBACK_URL', base_url + '/auth/callback'), |     callback_url=getenv('OIDC_CALLBACK_URL', base_url + '/auth/callback'), | ||||||
|     client_id = oidc_client_id, |     client_id = oidc_client_id, | ||||||
|     cookie_name=getenv('OIDC_COOKIE_NAME', 'oidc_' + oidc_client_id), |     cookie_name=getenv('OIDC_COOKIE_NAME', 'oidc_' + oidc_client_id), | ||||||
|  |  | ||||||
|  | @ -33,13 +33,13 @@ dbpassword = None | ||||||
| dbschema = None | dbschema = None | ||||||
| 
 | 
 | ||||||
| # authentication settings | # authentication settings | ||||||
| oidc_provider = 'testing:' | oidc_provider = 'test://testing' | ||||||
| oidc_client_id = getenv('OIDC_CLIENT_ID', '12345') | oidc_client_id = getenv('OIDC_CLIENT_ID', '12345') | ||||||
| oidc_params = dict( | oidc_params = dict( | ||||||
|     auth_url=getenv('OIDC_PROVIDER_URL', oidc_provider + '/oauth/v2/authorize'), |     op_config_url=oidc_provider + '/.well-known/openid-configuration', | ||||||
|     token_url=getenv('OIDC_TOKEN_URL', oidc_provider + '/oauth/v2/token'), |     op_uris=None, | ||||||
|     userinfo_url=getenv('OIDC_USERINFO_URL', oidc_provider + '/oidc/v1/userinfo'), |     op_keys=None, | ||||||
|     callback_url=getenv('OIDC_CALLBACK_URL', base_url + '/auth_callback'), |     callback_url=getenv('OIDC_CALLBACK_URL', base_url + '/auth/callback'), | ||||||
|     client_id=oidc_client_id, |     client_id=oidc_client_id, | ||||||
|     principal_prefix=getenv('OIDC_PRINCIPAL_PREFIX', 'loops.'), |     principal_prefix=getenv('OIDC_PRINCIPAL_PREFIX', 'loops.'), | ||||||
|     cookie_name=getenv('OIDC_COOKIE_NAME', 'oidc_' + oidc_client_id), |     cookie_name=getenv('OIDC_COOKIE_NAME', 'oidc_' + oidc_client_id), | ||||||
|  |  | ||||||
|  | @ -79,13 +79,19 @@ class Principal: | ||||||
| 
 | 
 | ||||||
| class Authenticator(DummyFolder): | class Authenticator(DummyFolder): | ||||||
| 
 | 
 | ||||||
|     prefix = 'auth' |     prefix = 'auth.oidc' | ||||||
|  | 
 | ||||||
|  |     oidcProviderUris = ['authorization_endpoint', 'token_endpoint',  | ||||||
|  |                         'introspection_endpoint', 'userinfo_endpoint', | ||||||
|  |                         'revocation_endpoint', 'end_session_endpoint', | ||||||
|  |                         'device_authorization_endpoint', 'jwks_uri'] | ||||||
| 
 | 
 | ||||||
|     def __init__(self, request): |     def __init__(self, request): | ||||||
|         self.request = request |         self.request = request | ||||||
|         self.params = config.oidc_params |         self.params = config.oidc_params | ||||||
|         self.reqUrl = config.base_url |         self.reqUrl = config.base_url | ||||||
|         self.setCrypt(self.params.get('cookie_crypt')) |         self.setCrypt(self.params.get('cookie_crypt')) | ||||||
|  |         self.loadOidcProviderData() | ||||||
| 
 | 
 | ||||||
|     def setReqUrl(self, base, path): |     def setReqUrl(self, base, path): | ||||||
|         self.reqUrl = '/'.join((base, path)) |         self.reqUrl = '/'.join((base, path)) | ||||||
|  | @ -120,7 +126,8 @@ class Authenticator(DummyFolder): | ||||||
|                 request_uri=self.reqUrl, |                 request_uri=self.reqUrl, | ||||||
|         ) |         ) | ||||||
|         self.storeSession(dict(state=state, nonce=nonce, code_verifier=codeVerifier)) |         self.storeSession(dict(state=state, nonce=nonce, code_verifier=codeVerifier)) | ||||||
|         loginUrl = '?'.join((self.params['auth_url'], urlencode(args))) |         authUrl = self.params['op_uris']['authorization_endpoint'] | ||||||
|  |         loginUrl = '?'.join((authUrl, urlencode(args))) | ||||||
|         logger.debug('login: URL %s', loginUrl) |         logger.debug('login: URL %s', loginUrl) | ||||||
|         req.response.redirect(loginUrl, trusted=True) |         req.response.redirect(loginUrl, trusted=True) | ||||||
| 
 | 
 | ||||||
|  | @ -138,11 +145,13 @@ class Authenticator(DummyFolder): | ||||||
|                 code_verifier=sdata['code_verifier'] |                 code_verifier=sdata['code_verifier'] | ||||||
|         ) |         ) | ||||||
|         # !set header: 'Content-Type: application/x-www-form-urlencoded' |         # !set header: 'Content-Type: application/x-www-form-urlencoded' | ||||||
|         tokenResponse = requests.post(self.params['token_url'], data=args) |         tokenUrl = self.params['op_uris']['token_endpoint'] | ||||||
|  |         tokenResponse = requests.post(tokenUrl, data=args) | ||||||
|         tdata =  tokenResponse.json() |         tdata =  tokenResponse.json() | ||||||
|         #print('*** token response', tdata) |         #print('*** token response', tdata) | ||||||
|         headers = dict(Authorization='Bearer ' + tdata['access_token']) |         headers = dict(Authorization='Bearer ' + tdata['access_token']) | ||||||
|         userInfo = requests.get(self.params['userinfo_url'], headers=headers) |         userInfoUrl = self.params['op_uris']['userinfo_endpoint'] | ||||||
|  |         userInfo = requests.get(userInfoUrl, headers=headers) | ||||||
|         userData = userInfo.json() |         userData = userInfo.json() | ||||||
|         #print('*** user data', userData) |         #print('*** user data', userData) | ||||||
|         groupInfo = userData.get('urn:zitadel:iam:org:project:roles', {}) |         groupInfo = userData.get('urn:zitadel:iam:org:project:roles', {}) | ||||||
|  | @ -194,6 +203,17 @@ class Authenticator(DummyFolder): | ||||||
|         data = json.loads(cookie) |         data = json.loads(cookie) | ||||||
|         return data |         return data | ||||||
| 
 | 
 | ||||||
|  |     def loadOidcProviderData(self, force=False): | ||||||
|  |         if config.oidc_provider.startswith('test'): | ||||||
|  |             return | ||||||
|  |         if force or self.params.get('op_uris') is None: | ||||||
|  |             uris = self.params['op_uris'] = {} | ||||||
|  |             opData = requests.get(self.params['op_config_url']).json() | ||||||
|  |             for key in self.oidcProviderUris: | ||||||
|  |                 uris[key] = opData[key] | ||||||
|  |         if force or self.params.get('op_keys') is None: | ||||||
|  |             self.params['op_keys'] = requests.get(uris['jwks_uri']).json() | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @register('auth', Root) | @register('auth', Root) | ||||||
| def authView(context, request): | def authView(context, request): | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue