Skip to content

Commit

Permalink
Merge pull request #323 from TeskaLabs/feature/log-successful-authori…
Browse files Browse the repository at this point in the history
…zation

Log successful authorization requests
  • Loading branch information
byewokko authored Nov 16, 2023
2 parents a6e71d8 + ef68ffa commit eb0ffd6
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## v23.44 (release candidate)

### Pre-releases
- `v23.44-alpha6`
- `v23.44-alpha5`
- `v23.44-alpha4`
- `v23.44-alpha3`
Expand All @@ -16,6 +17,7 @@
- Fix default authorize parameter values when redirecting (#313, PLUM Sprint 231020)

### Features
- Log successful authorization requests (#323, INDIGO Sprint 231110, `v23.44-alpha6`)
- Lower client ID length limit (#322, INDIGO Sprint 231110, `v23.44-alpha5`)
- Include client ID and scope in session detail (#318, INDIGO Sprint 231027, `v23.44-alpha4`)
- Reduce grafana sync frequency (#317, INDIGO Sprint 231027, `v23.44-alpha3`)
Expand Down
15 changes: 11 additions & 4 deletions seacatauth/cookie/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import asab.exceptions

from .. import exceptions
from ..generic import nginx_introspection, get_bearer_token_value
from .. import generic
from .utils import set_cookie, delete_cookie
from ..openidconnect.utils import TokenRequestErrorResponseCode

Expand Down Expand Up @@ -164,7 +164,7 @@ async def nginx(self, request):
response = aiohttp.web.HTTPUnauthorized()
else:
try:
response = await nginx_introspection(request, session, self.App)
response = await generic.nginx_introspection(request, session, self.App)
except Exception as e:
L.exception("Introspection failed: {}".format(e))
response = aiohttp.web.HTTPUnauthorized()
Expand Down Expand Up @@ -249,7 +249,7 @@ async def nginx_anonymous(self, request):
response = aiohttp.web.HTTPUnauthorized()
else:
try:
response = await nginx_introspection(request, session, self.App)
response = await generic.nginx_introspection(request, session, self.App)
except Exception as e:
L.exception("Introspection failed: {}".format(e))
response = aiohttp.web.HTTPUnauthorized()
Expand Down Expand Up @@ -399,7 +399,7 @@ async def _bouncer(self, request, parameters):
except exceptions.NoCookieError:
old_session = None

token_value = get_bearer_token_value(request)
token_value = generic.get_bearer_token_value(request)
if old_session is None and token_value is not None:
old_session = await self.CookieService.OpenIdConnectService.get_session_by_access_token(token_value)
if old_session is None:
Expand Down Expand Up @@ -447,6 +447,13 @@ async def _bouncer(self, request, parameters):
return asab.web.rest.json_response(
request, {"error": TokenRequestErrorResponseCode.InvalidRequest}, status=400)

L.log(asab.LOG_NOTICE, "Cookie request granted", struct_data={
"cid": session.Credentials.Id,
"sid": session.Id,
"client_id": session.OAuth2.ClientId,
"from_info": generic.get_request_access_ips(request),
"redirect_uri": redirect_uri})

return response


Expand Down
27 changes: 16 additions & 11 deletions seacatauth/openidconnect/handler/authorize.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from ... import exceptions
from ..utils import AuthErrorResponseCode, AUTHORIZE_PARAMETERS
from ..pkce import InvalidCodeChallengeMethodError, InvalidCodeChallengeError
from ...generic import urlparse, urlunparse

#

Expand Down Expand Up @@ -307,10 +306,7 @@ async def authorization_code_flow(
raise RedirectUriError(redirect_uri, client_id) from e

# Extract request source
from_info = [request.remote]
ff = request.headers.get("X-Forwarded-For")
if ff is not None:
from_info.extend(ff.split(", "))
from_info = generic.get_request_access_ips(request)

# Decide whether this is an openid or cookie request
try:
Expand Down Expand Up @@ -546,7 +542,8 @@ async def authorization_code_flow(
return await self.reply_with_successful_response(
new_session, scope, redirect_uri, state,
code_challenge=code_challenge,
code_challenge_method=code_challenge_method)
code_challenge_method=code_challenge_method,
from_info=from_info)

async def _build_cookie_entry_redirect_uri(self, client_dict, redirect_uri):
"""
Expand Down Expand Up @@ -643,7 +640,8 @@ async def reply_with_successful_response(
self, session, scope: list, redirect_uri: str,
state: str = None,
code_challenge: str = None,
code_challenge_method: str = None
code_challenge_method: str = None,
from_info: list = None
):
"""
https://openid.net/specs/openid-connect-core-1_0.html
Expand Down Expand Up @@ -692,6 +690,13 @@ async def reply_with_successful_response(
text="""<!doctype html>\n<html lang="en">\n<head></head><body>...</body>\n</html>\n"""
)

L.log(asab.LOG_NOTICE, "Authorization successful", struct_data={
"cid": session.Credentials.Id,
"sid": session.Id,
"client_id": session.OAuth2.ClientId,
"scope": " ".join(scope),
"from_info": from_info,
"redirect_uri": redirect_uri})
return response


Expand Down Expand Up @@ -902,21 +907,21 @@ def _build_login_uri(self, client_dict, login_query_params):
if login_uri is None:
login_uri = "{}{}".format(self.AuthWebuiBaseUrl, self.LoginPath)

parsed = urlparse(login_uri)
parsed = generic.urlparse(login_uri)
if parsed["fragment"] != "":
# If the Login URI contains fragment, add the login params into the fragment query
fragment_parsed = urlparse(parsed["fragment"])
fragment_parsed = generic.urlparse(parsed["fragment"])
query = urllib.parse.parse_qs(fragment_parsed["query"])
query.update(login_query_params)
fragment_parsed["query"] = urllib.parse.urlencode(query)
parsed["fragment"] = urlunparse(**fragment_parsed)
parsed["fragment"] = generic.urlunparse(**fragment_parsed)
else:
# If the Login URI contains no fragment, add the login params into the regular URL query
query = urllib.parse.parse_qs(parsed["query"])
query.update(login_query_params)
parsed["query"] = urllib.parse.urlencode(query)

return urlunparse(**parsed)
return generic.urlunparse(**parsed)


def _validate_request_parameters(self, request_parameters):
Expand Down
10 changes: 8 additions & 2 deletions seacatauth/openidconnect/handler/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from ..utils import TokenRequestErrorResponseCode
from ..pkce import CodeChallengeFailedError
from ... import exceptions
from ...generic import get_bearer_token_value
from ... import generic

#

Expand Down Expand Up @@ -147,7 +147,7 @@ async def _token_request_authorization_code(self, request, qs_data):
new_session = await self.SessionService.inherit_track_id_from_root(new_session)
if new_session.TrackId is None:
# Obtain the old session by request access token or cookie
token_value = get_bearer_token_value(request)
token_value = generic.get_bearer_token_value(request)
if token_value is not None:
old_session = await self.OpenIdConnectService.get_session_by_access_token(token_value)
if old_session is None:
Expand Down Expand Up @@ -189,6 +189,12 @@ async def _token_request_authorization_code(self, request, qs_data):
data["expires_in"] = int(
(new_session.Session.Expiration - datetime.datetime.now(datetime.timezone.utc)).total_seconds())

L.log(asab.LOG_NOTICE, "Token request granted", struct_data={
"cid": new_session.Credentials.Id,
"sid": new_session.Id,
"client_id": new_session.OAuth2.ClientId,
"from_info": generic.get_request_access_ips(request)})

return asab.web.rest.json_response(request, data, headers=headers)


Expand Down

0 comments on commit eb0ffd6

Please sign in to comment.