Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Commit

Permalink
feat: add AUTHORIZE hook to override credential check during login pr…
Browse files Browse the repository at this point in the history
…ocess (#339)
  • Loading branch information
adrysn authored Oct 5, 2020
1 parent ddc125e commit 0e4bfb5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
1 change: 1 addition & 0 deletions changes/339.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add hooking point for AUTHORIZE with FIRST_COMPLETED requirement.
29 changes: 26 additions & 3 deletions src/ai/backend/gateway/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from ai.backend.common.logging import Logger, BraceStyleAdapter
from ai.backend.common.plugin.hook import (
ALL_COMPLETED,
FIRST_COMPLETED,
PASSED,
)
from .exceptions import (
Expand Down Expand Up @@ -537,9 +538,31 @@ async def authorize(request: web.Request, params: Any) -> web.Response:
raise InvalidAPIParameters('Unsupported authorization type')
log.info('AUTH.AUTHORIZE(d:{0[domain]}, u:{0[username]}, passwd:****, type:{0[type]})', params)
dbpool = request.app['dbpool']
user = await check_credential(
dbpool,
params['domain'], params['username'], params['password'])

# [Hooking point for AUTHORIZE with the FIRST_COMPLETED requirement]
# The hook handlers should accept the whole ``params`` dict, and optional
# ``dbpool`` parameter (if the hook needs to query to database).
# They should return a corresponding Backend.AI user object after performing
# their own authentication steps, like LDAP authentication, etc.
params['dbpool'] = dbpool # hack to execute db commands in the hook (TODO: more general logic)
hook_result = await request.app['hook_plugin_ctx'].dispatch(
'AUTHORIZE',
(params, dbpool),
return_when=FIRST_COMPLETED,
)
if hook_result.status != PASSED:
# Did not pass AUTHORIZED hook
reason = hook_result.reason
raise RejectedByHook(extra_msg=reason)
elif 'user' in ChainMap(*hook_result.result):
# Passed one of AUTHORIZED hook
user = ChainMap(*hook_result.result)['user']
else:
# No AUTHORIZE hook is defined (proceed with normal login)
user = await check_credential(
dbpool,
params['domain'], params['username'], params['password']
)
if user is None:
raise AuthorizationFailed('User credential mismatch.')
if user.get('status') == UserStatus.BEFORE_VERIFICATION:
Expand Down

0 comments on commit 0e4bfb5

Please # to comment.