Skip to content

Commit

Permalink
Merge 2f2f830 into 572872b
Browse files Browse the repository at this point in the history
  • Loading branch information
Avantol13 committed Sep 3, 2020
2 parents 572872b + 2f2f830 commit 79f83ae
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 5 deletions.
4 changes: 2 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": null,
"lines": null
},
"generated_at": "2020-07-20T16:22:58Z",
"generated_at": "2020-09-03T18:35:47Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -97,7 +97,7 @@
"hashed_secret": "5d07e1b80e448a213b392049888111e1779a52db",
"is_secret": false,
"is_verified": false,
"line_number": 508,
"line_number": 528,
"type": "Secret Keyword"
}
],
Expand Down
22 changes: 19 additions & 3 deletions fence/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from fence.resources.openid.microsoft_oauth2 import (
MicrosoftOauth2Client as MicrosoftClient,
)
from fence.resources.openid.okta_oauth2 import OktaOauth2Client as OktaClient
from fence.resources.openid.generic_oauth2 import GenericOauth2Client as GenericClient
from fence.resources.openid.orcid_oauth2 import OrcidOauth2Client as ORCIDClient
from fence.resources.openid.synapse_oauth2 import SynapseOauth2Client as SynapseClient
from fence.resources.openid.ras_oauth2 import RASOauth2Client as RASClient
Expand Down Expand Up @@ -338,9 +340,7 @@ def _setup_oidc_clients(app):
# Add OIDC client for RAS if configured.
if "ras" in oidc:
app.ras_client = RASClient(
oidc["ras"],
HTTP_PROXY=config.get("HTTP_PROXY"),
logger=logger,
oidc["ras"], HTTP_PROXY=config.get("HTTP_PROXY"), logger=logger,
)

# Add OIDC client for Synapse if configured.
Expand All @@ -357,6 +357,22 @@ def _setup_oidc_clients(app):
logger=logger,
)

# Add OIDC client for Okta if configured
if "okta" in oidc:
app.okta_client = OktaClient(
config["OPENID_CONNECT"]["okta"],
HTTP_PROXY=config.get("HTTP_PROXY"),
logger=logger,
)

# Add OIDC client for generic IDP if configured
if "generic" in oidc:
app.generic_client = GenericClient(
config["OPENID_CONNECT"]["generic"],
HTTP_PROXY=config.get("HTTP_PROXY"),
logger=logger,
)

# Add OIDC client for Amazon Cognito if configured.
if "cognito" in oidc:
app.cognito_client = CognitoClient(
Expand Down
14 changes: 14 additions & 0 deletions fence/blueprints/login/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from fence.blueprints.login.google import GoogleLogin, GoogleCallback
from fence.blueprints.login.shib import ShibbolethLogin, ShibbolethCallback
from fence.blueprints.login.microsoft import MicrosoftLogin, MicrosoftCallback
from fence.blueprints.login.okta import OktaLogin, OktaCallback
from fence.blueprints.login.generic import GenericLogin, GenericCallback
from fence.blueprints.login.orcid import ORCIDLogin, ORCIDCallback
from fence.blueprints.login.ras import RASLogin, RASCallback
from fence.blueprints.login.synapse import SynapseLogin, SynapseCallback
Expand All @@ -34,6 +36,8 @@
"orcid": "orcid",
"synapse": "synapse",
"microsoft": "microsoft",
"okta": "okta",
"generic": "generic",
"cognito": "cognito",
"ras": "ras",
}
Expand Down Expand Up @@ -275,6 +279,16 @@ def provider_info(login_details):
MicrosoftCallback, "/microsoft/login", strict_slashes=False
)

if "okta" in configured_idps:
blueprint_api.add_resource(OktaLogin, "/okta", strict_slashes=False)
blueprint_api.add_resource(OktaCallback, "/okta/login", strict_slashes=False)

if "generic" in configured_idps:
blueprint_api.add_resource(GenericLogin, "/generic", strict_slashes=False)
blueprint_api.add_resource(
GenericCallback, "/generic/login", strict_slashes=False
)

if "cognito" in configured_idps:
blueprint_api.add_resource(CognitoLogin, "/cognito", strict_slashes=False)
blueprint_api.add_resource(
Expand Down
19 changes: 19 additions & 0 deletions fence/blueprints/login/generic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import flask

from fence.models import IdentityProvider
from fence.resources.openid.generic_oauth2 import GENERIC_IDP_NAME
from fence.blueprints.login.base import DefaultOAuth2Login, DefaultOAuth2Callback


class GenericLogin(DefaultOAuth2Login):
def __init__(self):
super(GenericLogin, self).__init__(
idp_name=GENERIC_IDP_NAME, client=flask.current_app.generic_client,
)


class GenericCallback(DefaultOAuth2Callback):
def __init__(self):
super(GenericCallback, self).__init__(
idp_name=GENERIC_IDP_NAME, client=flask.current_app.generic_client,
)
19 changes: 19 additions & 0 deletions fence/blueprints/login/okta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import flask

from fence.models import IdentityProvider
from fence.resources.openid.okta_oauth2 import OKTA_IDP_NAME
from fence.blueprints.login.base import DefaultOAuth2Login, DefaultOAuth2Callback


class OktaLogin(DefaultOAuth2Login):
def __init__(self):
super(OktaLogin, self).__init__(
idp_name=OKTA_IDP_NAME, client=flask.current_app.okta_client,
)


class OktaCallback(DefaultOAuth2Callback):
def __init__(self):
super(OktaCallback, self).__init__(
idp_name=OKTA_IDP_NAME, client=flask.current_app.okta_client,
)
18 changes: 18 additions & 0 deletions fence/config-default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@ OPENID_CONNECT:
# WARNING: DO NOT ENABLE IN PRODUCTION (for testing purposes only)
mock: false
mock_default_user: 'test@example.com'
# For information on configuring an Okta tenant as an OIDC IdP refer to Okta documentation at:
# https://developer.okta.com/docs/reference/api/oidc/#2-okta-as-the-identity-platform-for-your-app-or-api
okta:
discovery_url: ''
client_id: ''
client_secret: ''
redirect_url: '{{BASE_URL}}/login/okta/login/'
# generic is for use with an OIDC compliant IdP. It requires the discover URL to parse the various OIDC endpoints required.
generic:
discovery_url: ''
client_id: ''
client_secret: ''
redirect_url: '{{BASE_URL}}/login/generic/login/'
cognito:
# You must create a user pool in order to have a discovery url
discovery_url: 'https://cognito-idp.{REGION}.amazonaws.com/{USER-POOL-ID}/.well-known/openid-configuration'
Expand Down Expand Up @@ -253,6 +266,11 @@ LOGIN_OPTIONS: [] # !!! remove the empty list to enable login options!
# idp: orcid
# - name: 'Microsoft Login'
# idp: microsoft
# - name: 'Okta Login'
# idp: okta
# Generic Login: You may want to edit the name to reflect your OIDC idP.
# - name: 'Generic Login'
# idp: generic
# # Cognito login: You may want to edit the name to reflect Cognito's IdP,
# # especially if Cognito is only using one IdP
# - name: 'Login from Cognito'
Expand Down
43 changes: 43 additions & 0 deletions fence/resources/openid/generic_oauth2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import json
from .idp_oauth2 import Oauth2ClientBase

GENERIC_IDP_NAME = "generic"


class GenericOauth2Client(Oauth2ClientBase):
def __init__(self, settings, logger, HTTP_PROXY=None):
super(GenericOauth2Client, self).__init__(
settings,
logger,
scope="openid email",
discovery_url=settings["discovery_url"],
idp="Generic",
HTTP_PROXY=HTTP_PROXY,
)

def get_auth_url(self):
"""
Get authorization uri from discovery doc
"""
authorization_endpoint = self.get_value_from_discovery_doc(
"authorization_endpoint", "",
)
uri, _ = self.session.create_authorization_url(
authorization_endpoint, prompt="login"
)

return uri

def get_user_id(self, code):
try:
token_endpoint = self.get_value_from_discovery_doc("token_endpoint", "",)
jwks_endpoint = self.get_value_from_discovery_doc("jwks_uri", "",)
claims = self.get_jwt_claims_identity(token_endpoint, jwks_endpoint, code)

if claims["email"]:
return {"email": claims["email"]}
else:
return {"error": "Can't get user's email!"}
except Exception as e:
self.logger.exception("Can't get user info")
return {"error": "Can't get your email: {}".format(e)}
43 changes: 43 additions & 0 deletions fence/resources/openid/okta_oauth2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import json
from .idp_oauth2 import Oauth2ClientBase

OKTA_IDP_NAME = "okta"


class OktaOauth2Client(Oauth2ClientBase):
def __init__(self, settings, logger, HTTP_PROXY=None):
super(OktaOauth2Client, self).__init__(
settings,
logger,
scope="openid email",
discovery_url=settings["discovery_url"],
idp="Okta",
HTTP_PROXY=HTTP_PROXY,
)

def get_auth_url(self):
"""
Get authorization uri from discovery doc
"""
authorization_endpoint = self.get_value_from_discovery_doc(
"authorization_endpoint", "",
)
uri, _ = self.session.create_authorization_url(
authorization_endpoint, prompt="login"
)

return uri

def get_user_id(self, code):
try:
token_endpoint = self.get_value_from_discovery_doc("token_endpoint", "",)
jwks_endpoint = self.get_value_from_discovery_doc("jwks_uri", "",)
claims = self.get_jwt_claims_identity(token_endpoint, jwks_endpoint, code)

if claims["email"]:
return {"email": claims["email"]}
else:
return {"error": "Can't get user's email!"}
except Exception as e:
self.logger.exception("Can't get user info")
return {"error": "Can't get your email: {}".format(e)}

0 comments on commit 79f83ae

Please sign in to comment.