Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PBENCH-865 First pass at implementing OIDC token decode framework #2942

Merged
merged 28 commits into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fe98582
First pass at OIDC token validation framework
npalaska Jul 12, 2022
095b59c
add keycloak admin functionality
npalaska Aug 1, 2022
6962802
Add keycloak session management click interface
npalaska Aug 2, 2022
22f7829
unit tests and more admin functionality
npalaska Aug 3, 2022
4a00303
remove Keycloak admin cli, make keycloak client more general
npalaska Aug 8, 2022
bb2e10d
more refactoring
npalaska Aug 8, 2022
98d6989
update docstrings, some more refactoring
npalaska Aug 9, 2022
f4e8041
add idp token management seq diagram
npalaska Aug 10, 2022
c7467de
Address another round of comments
npalaska Aug 15, 2022
d7d8f22
update seq diagram
npalaska Aug 15, 2022
69fac11
more updates to seq diagram
npalaska Aug 16, 2022
67a87fe
few more comments in seq diagram
npalaska Aug 16, 2022
d81ca3b
more refactoring based on comments
npalaska Aug 16, 2022
34af9bc
unit test for custom token expiry and handle requests failures
npalaska Aug 16, 2022
9b58541
more seq diagram update
npalaska Aug 16, 2022
24b9219
more comments
npalaska Aug 17, 2022
bd3cf43
remove some placeholder type unit tests
npalaska Aug 17, 2022
75c7685
Major update to the seq diagram
npalaska Aug 23, 2022
4b8043a
fix minor typos and formatting
npalaska Aug 24, 2022
ecac6d2
comment feedback
npalaska Aug 24, 2022
af60bf0
minor review changes
npalaska Aug 25, 2022
7eafba3
more review feedback
npalaska Aug 29, 2022
c051768
more refactoring changes
npalaska Aug 30, 2022
5c93a85
remove custom token expiry functionality
npalaska Aug 31, 2022
5690c7e
review comments
npalaska Sep 1, 2022
39ec2a1
Add browser context to seq diagram
npalaska Sep 7, 2022
3946008
seq diagram comments
npalaska Sep 14, 2022
3fe6e04
fix typos
npalaska Sep 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions docs/user_authentication/third_party_token_management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

```sequence {theme: 'simple'}
portante marked this conversation as resolved.
Show resolved Hide resolved
title Third-party Token Management

participant Pbench-Server
participant Browser
participant Identity-Broker
participant Identity-Provider

autonumber 1
activate Browser #red

rbox over Browser: Dashboard
Browser->Pbench-Server: GET Pbench client ID

Pbench-Server->Browser: 200 Response

note right of Pbench-Server:{identity_broker_auth_URI: <auth_URI>\nclient_id: <pbench_client_id>\nclient_secret: <pbench_client_secret> # optional\n}

note over Browser:User clicks login
abox over Browser: Dashboard instructs the browser to \nload identity broker authentication page \nurl that was supplied by the Pbench-server.

deactivate Browser

Browser->Identity-Broker:GET identity broker auth URI\n(Authentication Request)

note right of Browser:GET request:\n<identity_broker_auth_URI>\n?client_id=<pbench_client_id>\n&response_type=code\n&redirect_uri=<dashboard_URI>\n&scope=openid

Identity-Broker->Browser: 200 Response

activate Browser #blue
rbox over Browser: Identity-Broker
note over Browser:User selects an identity provider from the list

abox over Browser:Identity broker instructs the browser to \nload identity provider authentication page

deactivate Browser

Browser->Identity-Provider:GET identity provider auth page
note right of Browser:GET request:\n<identity_provider_auth_URI>\n?client_id=<client_id as registered on identity provider>\n&response_type=code\n&redirect_uri=<identity_broker_URI>\n&scope=openid

Identity-Provider->Browser:303 Response\n(Redirect to identity provider auth page)

Browser->Identity-Provider:GET request auth Page
Browser<-Identity-Provider:200 Response

activate Browser #green
rbox over Browser: Identity-Provider

note over Browser:User challenge credentials and consent

abox over Browser:Identity provider instructs the browser to \nsend the request and load the response

deactivate Browser

Browser->Identity-Provider: GET/POST authentication request

Identity-Provider->Browser: 302/303 Response
note left of Identity-Provider:Redirect Location:\n<identity_broker_URI>\n?code=<auth_code>\n&state=<session_state_id>

Identity-Broker<-Browser:GET Redirect location (identity broker URI)

note over Identity-Broker:Identity federation\na. Checks the validity of response from the identity provider\nb. Imports and creates user identity from the token\nc. Links the user identity with the identity provider

Identity-Broker->Browser:302 Authentication Response\n(Redirect back to Pbench dashboard)

note left of Identity-Broker:Redirect Location:\n<dashboard_URI>\n?code=<identity_broker_auth_code>\n&state=<session_state_id>

Browser->Pbench-Server: GET Pbench-dashboard redirect location

Pbench-Server->Browser: 200 Response

activate Browser #red
rbox over Browser: Dashboard

Browser->Identity-Broker:POST Request to token endpoint

note right of Browser:POST request:\npost <identity_broker_token_endpoint>\npayload:\n{code: <identity_broker_auth_code>\nclient_id: <pbench_client_id>\nredirect_uri: <dashboard_URI>\n}

Identity-Broker->Browser: 200 Token Response

note left of Identity-Broker:token response:\n{\n access_token: <identity_broker_access_token>,\n expires_in: <number_of_seconds>,\n refresh_expires_in: <number_of_seconds>,\n refresh_token: <refresh_token>,\n token_type: "Bearer",\n id_token: <id_token>\n session_state: <session_id>,\n scope: <openid_email_profile>\n}

==Authorization setup complete; the steps below may be repeated to issue a series of requests==

Browser->Pbench-Server: POST /api/v1/<restricted_endpoint> request (Bearer: Pbench access token)

note over Pbench-Server:Validation and identity extraction\nfrom the Pbench token

alt Authenticated user is authorized for resource
Pbench-Server->Browser: 200 /api/v1/<restricted_endpoint> response
else Authenticated user is not authorized for resource
Pbench-Server->Browser:403 /api/v1/<restricted_endpoint> response
else Authorization token expired or invalid
Pbench-Server->Browser:401 /api/v1/<restricted_endpoint> response
end

space
deactivate Browser
destroysilent Pbench-Server
destroysilent Browser
destroysilent Identity-Broker
destroysilent Identity-Provider
```
webbnh marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion lib/pbench/server/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from pbench.common.exceptions import BadConfig, ConfigFileNotSpecified
from pbench.common.logger import get_pbench_logger
from pbench.server import PbenchServerConfig
from pbench.server.api.auth import Auth
from pbench.server.api.resources.datasets_daterange import DatasetsDateRange
from pbench.server.api.resources.datasets_inventory import DatasetsInventory
from pbench.server.api.resources.datasets_list import DatasetsList
Expand All @@ -39,6 +38,7 @@
from pbench.server.api.resources.server_configuration import ServerConfiguration
from pbench.server.api.resources.upload_api import Upload
from pbench.server.api.resources.users_api import Login, Logout, RegisterUser, UserAPI
from pbench.server.auth.auth import Auth
from pbench.server.database import init_db
from pbench.server.database.database import Database

Expand Down
2 changes: 1 addition & 1 deletion lib/pbench/server/api/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from sqlalchemy.orm.query import Query

from pbench.server import JSON, JSONOBJECT, JSONVALUE, PbenchServerConfig
from pbench.server.api.auth import Auth
from pbench.server.auth.auth import Auth
from pbench.server.database.models.datasets import (
Dataset,
DatasetNotFound,
Expand Down
2 changes: 1 addition & 1 deletion lib/pbench/server/api/resources/datasets_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from flask.wrappers import Request, Response

from pbench.server import PbenchServerConfig
from pbench.server.api.auth import Auth
from pbench.server.api.resources import (
API_AUTHORIZATION,
API_METHOD,
Expand All @@ -20,6 +19,7 @@
ParamType,
Schema,
)
from pbench.server.auth.auth import Auth
from pbench.server.database.models.datasets import (
Metadata,
MetadataBadValue,
Expand Down
2 changes: 1 addition & 1 deletion lib/pbench/server/api/resources/query_apis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import requests

from pbench.server import JSON, PbenchServerConfig
from pbench.server.api.auth import Auth
from pbench.server.api.resources import (
API_AUTHORIZATION,
API_METHOD,
Expand All @@ -27,6 +26,7 @@
SchemaError,
UnauthorizedAccess,
)
from pbench.server.auth.auth import Auth
from pbench.server.database.models.datasets import Dataset
from pbench.server.database.models.template import Template
from pbench.server.database.models.users import User
Expand Down
2 changes: 1 addition & 1 deletion lib/pbench/server/api/resources/upload_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import humanize

from pbench.common.utils import Cleanup, validate_hostname
from pbench.server.api.auth import Auth
from pbench.server.auth.auth import Auth
from pbench.server.database.models.datasets import (
Dataset,
DatasetDuplicate,
Expand Down
9 changes: 6 additions & 3 deletions lib/pbench/server/api/resources/users_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import timedelta
from http import HTTPStatus
from typing import NamedTuple

Expand All @@ -8,7 +9,7 @@
import jwt
from sqlalchemy.exc import IntegrityError, SQLAlchemyError

from pbench.server.api.auth import Auth
from pbench.server.auth.auth import Auth
from pbench.server.database.models.active_tokens import ActiveTokens
from pbench.server.database.models.server_config import ServerConfig
from pbench.server.database.models.users import User
Expand Down Expand Up @@ -150,7 +151,8 @@ def __init__(self, config, logger, auth):
def post(self):
"""
Post request for logging in user.
The user is allowed to re-login multiple times and each time a new valid auth token will be provided
The user is allowed to re-login multiple times and each time a new
valid auth token will be returned.

This requires a JSON data with required user metadata fields
{
Expand Down Expand Up @@ -210,7 +212,8 @@ def post(self):

try:
auth_token = self.auth.encode_auth_token(
self.token_expire_duration, user.id
time_delta=timedelta(minutes=int(self.token_expire_duration)),
user_id=user.id,
)
except (
jwt.InvalidIssuer,
Expand Down
Loading