forked from SUNET/cnaas-nms
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request SUNET#316 from Josephine-Rutten/feature.authentica…
…tionwithoauth Authentication setup
- Loading branch information
Showing
24 changed files
with
521 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,20 @@ | ||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v2.3.0 | ||
rev: v4.5.0 | ||
hooks: | ||
- id: check-yaml | ||
- id: end-of-file-fixer | ||
- id: trailing-whitespace | ||
- repo: https://github.com/psf/black | ||
rev: 22.10.0 | ||
rev: 23.11.0 | ||
hooks: | ||
- id: black | ||
- repo: https://github.com/pycqa/isort | ||
rev: 5.11.2 | ||
rev: 5.12.0 | ||
hooks: | ||
- id: isort | ||
name: isort (python) | ||
- repo: https://github.com/pycqa/flake8 | ||
rev: 5.0.4 | ||
rev: 6.1.0 | ||
hooks: | ||
- id: flake8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
oidc_conf_well_known_url: "well-known-openid-configuration-endpoint" | ||
oidc_client_secret: "xxx" | ||
oidc_client_id: "client-id" | ||
frontend_callback_url: "http://localhost/callback" | ||
oidc_enabled: False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,3 +33,5 @@ SQLAlchemy-Utils==0.38.3 | |
pydantic==1.10.2 | ||
Werkzeug==2.2.3 | ||
greenlet==3.0.1 | ||
Authlib==1.0.1 | ||
python-jose==3.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
from authlib.integrations.base_client.errors import MismatchingStateError, OAuthError | ||
from flask import current_app, redirect, url_for | ||
from flask_restx import Namespace, Resource | ||
from requests.models import PreparedRequest | ||
|
||
from cnaas_nms.api.generic import empty_result | ||
from cnaas_nms.app_settings import auth_settings | ||
from cnaas_nms.tools.log import get_logger | ||
from cnaas_nms.tools.security import get_identity, login_required | ||
from cnaas_nms.version import __api_version__ | ||
|
||
logger = get_logger() | ||
api = Namespace("auth", description="API for handling auth", prefix="/api/{}".format(__api_version__)) | ||
|
||
|
||
class LoginApi(Resource): | ||
def get(self): | ||
"""Function to initiate a login of the user. | ||
The user will be sent to the page to login. | ||
Our client info will also be checked. | ||
Note: | ||
We also discussed adding state to this function. | ||
That way you could be sent to the same page once you logged in. | ||
We would put the relevant information in a dictionary, | ||
base64 encode it and sent it around as a parameter. | ||
For now the application is small and it didn't seem needed. | ||
Returns: | ||
A HTTP redirect response to OIDC_CONF_WELL_KNOWN_URL we have defined. | ||
We give the auth call as a parameter to redirect after login is successfull. | ||
""" | ||
if not auth_settings.OIDC_ENABLED: | ||
return empty_result(status="error", data="Can't login when OIDC disabled"), 500 | ||
oauth_client = current_app.extensions["authlib.integrations.flask_client"] | ||
redirect_uri = url_for("auth_auth_api", _external=True) | ||
|
||
return oauth_client.connext.authorize_redirect(redirect_uri) | ||
|
||
|
||
class AuthApi(Resource): | ||
def get(self): | ||
"""Function to authenticate the user. | ||
This API call is called by the OAUTH login after the user has logged in. | ||
We get the users token and redirect them to right page in the frontend. | ||
Returns: | ||
A HTTP redirect response to the url in the frontend that handles the repsonse after login. | ||
The access token is a parameter in the url | ||
""" | ||
|
||
oauth_client = current_app.extensions["authlib.integrations.flask_client"] | ||
|
||
try: | ||
token = oauth_client.connext.authorize_access_token() | ||
except MismatchingStateError as e: | ||
logger.error("Exception during authorization of the access token: {}".format(str(e))) | ||
return ( | ||
empty_result( | ||
status="error", | ||
data="Exception during authorization of the access token. Please try to login again.", | ||
), | ||
502, | ||
) | ||
except OAuthError as e: | ||
logger.error("Missing information needed for authorization: {}".format(str(e))) | ||
return ( | ||
empty_result( | ||
status="error", | ||
data="The server is missing some information that is needed for authorization.", | ||
), | ||
500, | ||
) | ||
|
||
url = auth_settings.FRONTEND_CALLBACK_URL | ||
parameters = {"token": token["access_token"]} | ||
|
||
req = PreparedRequest() | ||
req.prepare_url(url, parameters) | ||
return redirect(req.url, code=302) | ||
|
||
|
||
class IdentityApi(Resource): | ||
@login_required | ||
def get(self): | ||
identity = get_identity() | ||
return identity | ||
|
||
|
||
api.add_resource(LoginApi, "/login") | ||
api.add_resource(AuthApi, "/auth") | ||
api.add_resource(IdentityApi, "/identity") |
Oops, something went wrong.