Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7dbb48e
added Azure button, added login_azure function, added azure-ad2-oauth…
christosachilleoudis May 9, 2022
8cb274a
now programatically setting redirect uri
christosachilleoudis May 18, 2022
c1e5368
added msal package
christosachilleoudis May 18, 2022
9d64436
restored markupsafe to 2.0.1
christosachilleoudis May 18, 2022
2a30c58
reset ember deps and added torii with --save-dev
christosachilleoudis May 18, 2022
ba7a1aa
upgrading to node:10
christosachilleoudis May 18, 2022
a037362
reading READIRECT_URI from environment
christosachilleoudis May 20, 2022
856788c
now printing original authorization token and error message
christosachilleoudis May 20, 2022
16ed840
now using environment variable
christosachilleoudis May 20, 2022
c478201
fixing syntax error
christosachilleoudis May 20, 2022
6292cd5
checking environment for secret_key and security_password_salt
christosachilleoudis May 31, 2022
d668ae8
added Azure AD icon inline
christosachilleoudis Jun 2, 2022
65dd504
using redirectUri returned by torii
christosachilleoudis Jun 2, 2022
516af3b
removed unused imports
christosachilleoudis Jun 2, 2022
6559eaf
deleted console logging
christosachilleoudis Jun 2, 2022
dc75440
restored formatting of webapp/app/setup/template.hbs
christosachilleoudis Jun 2, 2022
367c02b
undo formatting on webapp/app/login/template.hbs
christosachilleoudis Jun 2, 2022
99bada4
restored formattign of webapp/config/environment.js
christosachilleoudis Jun 2, 2022
f03297e
missed an extra }
christosachilleoudis Jun 2, 2022
dd6bda3
removed credentials from log statement
christosachilleoudis Jun 7, 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
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ raven = {extras = ["flask"], version = "*"}
redis = "*"
watchdog = "*"
weber_utils = "*"
msal = "*"

[dev-packages]
Flask-Loopback = "*"
Expand Down
322 changes: 296 additions & 26 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:8 as frontend-builder
FROM node:10 as frontend-builder
# build frontend
RUN npm install -g ember-cli

Expand Down
23 changes: 21 additions & 2 deletions flask_app/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from .config import get_runtime_config_private_dict
from .models import db, Role, User
from .utils.oauth2 import get_oauth2_identity
from .utils.oauth2 import get_oauth2_identity, get_oauth2_identity_azure

_logger = logbook.Logger(__name__)

Expand Down Expand Up @@ -52,9 +52,15 @@ def login():
return _login_with_credentials(credentials)

auth_code = credentials.get('authorizationCode')
if auth_code:
provider = credentials.get("provider")
redirect_uri = credentials.get("redirectUri")

if provider == "google-oauth2":
return _login_with_google_oauth2(auth_code)

if provider == "azure-ad2-oauth2":
return _login_with_azure_oauth2(auth_code, redirect_uri)

error_abort('No credentials were specified', code=requests.codes.unauthorized)


Expand Down Expand Up @@ -137,6 +143,19 @@ def _login_with_google_oauth2(auth_code):

return _make_success_login_response(user, user_info)

def _login_with_azure_oauth2(auth_code, redirect_uri):
"""Logs in with azure oath2"""
user_info = get_oauth2_identity_azure(auth_code, redirect_uri)
if not user_info:
error_abort('Could not complete OAuth2 exchange', code=requests.codes.unauthorized)

_check_alowed_email_domain(user_info)

user = get_or_create_user(user_info)
login_user(user)

return _make_success_login_response(user, user_info)


@auth.route("/logout", methods=['POST'])
def logout():
Expand Down
4 changes: 4 additions & 0 deletions flask_app/blueprints/api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def get_app_config():
'google_oauth2_enabled': False,
'google_oauth2_client_id': None,
'google_oauth2_client_secret': None,
'azure_oauth2_enabled': False,
'azure_oauth2_client_id': None,
'azure_oauth2_client_secret': None,
'azure_oauth2_tenant_id': None,
'ldap_login_enabled': False,
'ldap_uri': None,
'ldap_base_dn': None,
Expand Down
37 changes: 37 additions & 0 deletions flask_app/utils/oauth2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from httplib2 import Http
from apiclient.discovery import build
from oauth2client.client import OAuth2WebServerFlow
import msal

from .. import config

Expand Down Expand Up @@ -41,6 +42,42 @@ def get_oauth2_identity(auth_code):
_logger.debug('Found user info: {}', info)
return info

def get_oauth2_identity_azure(auth_code, redirect_uri):
"""Gets identity from azure auth_code"""

config_dict = config.get_runtime_config_private_dict()
client_id = config_dict['azure_oauth2_client_id']
client_secret = config_dict['azure_oauth2_client_secret']
authority = f"https://login.microsoftonline.com/{config_dict['azure_oauth2_tenant_id']}"

if not client_id:
_logger.error('No OAuth2 client id configured')
return

if not client_secret:
_logger.error('No OAuth2 client secret configured')
return

_logger.info('get_oauth2_identity: Using redirect URI {!r}', redirect_uri)

client = msal.ConfidentialClientApplication(
client_id, authority=authority,
client_credential=client_secret, token_cache=None)

token = client.acquire_token_by_authorization_code(code=auth_code, scopes=["User.read"], redirect_uri=redirect_uri)

if "error" in token:
_logger.error(token["error_description"])
assert False

user_info = token["id_token_claims"]

return {
"email" : user_info["email"],
"first_name" : user_info["name"].split()[0],
"last_name" : user_info["name"].split()[-1],
}


def _get_user_info(credentials):
http_client = Http()
Expand Down
3 changes: 2 additions & 1 deletion manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ def _ensure_conf():
if not os.path.isfile(private_filename):
with open(private_filename, 'w') as f:
for secret_name in ('SECRET_KEY', 'SECURITY_PASSWORD_SALT'):
f.write('{}: {!r}\n'.format(secret_name, _generate_secret_string()))
# either pull value from environment or generate random value
f.write('{}: {!r}\n'.format(secret_name, os.environ.get(secret_name, _generate_secret_string())))

def _generate_secret_string(length=50):
return "".join([random.choice(string.ascii_letters) for i in range(length)])
Expand Down
1 change: 1 addition & 0 deletions webapp/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ const App = Application.extend({

loadInitializers(App, config.modulePrefix);
config.torii.providers["google-oauth2"].redirectUri = window.location.origin;
config.torii.providers["azure-ad2-oauth2"].redirectUri = window.location.origin;
export default App;
5 changes: 5 additions & 0 deletions webapp/app/application/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export default Route.extend(ApplicationRouteMixin, {
let cfg = config.torii;
cfg.providers["google-oauth2"].apiKey =
model.runtime_config.google_oauth2_client_id;
cfg.providers["azure-ad2-oauth2"].apiKey =
model.runtime_config.azure_oauth2_client_id;
cfg.providers["azure-ad2-oauth2"].tenantId =
model.runtime_config.azure_oauth2_tenant_id;

this.load_current_user();
}
},
Expand Down
41 changes: 35 additions & 6 deletions webapp/app/login/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export default Controller.extend(UnauthenticatedRouteMixin, {
self.set("login_error", null);
const credentials = this.getProperties(["username", "password"]);
self.get("session").authenticate("authenticator:token", credentials).then(
function() {},
function() {
function () { },
function () {
self.set("login_error", "Invalid username and/or password");
}
);
Expand All @@ -28,24 +28,53 @@ export default Controller.extend(UnauthenticatedRouteMixin, {
self
.get("torii")
.open("google-oauth2")
.then(function(auth) {
.then(function (auth) {
return self

.get("session")
.authenticate("authenticator:token", auth)
.then(
function(data) {
function (data) {
return data;
},
function(error) {
function (error) {
self.set("login_error", error.error);
}
);
})
.finally(function() {
.finally(function () {
self.set("loading", false);
});

return;
},

login_azure() {
let self = this;
self.set("loading", true);
self.set("login_error", null);
self
.get("torii")
.open("azure-ad2-oauth2", { "response_type": "id_token+code" })
.then(function (auth) {
return self
.get("session")
.authenticate("authenticator:token", auth)
.then(
function (data) {
return data;
},
function (error) {
self.set("login_error", error.error);
}
);
})
.finally(function () {
self.set("loading", false);
});

return;
}

}
});
40 changes: 40 additions & 0 deletions webapp/app/login/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,45 @@
</div>
{{/if}}

{{#if runtime_config.azure_oauth2_enabled}}
<p class="text-center">
Or
</p>

<div class="form-group">
<button class="btn btn-lg btn-outline-secondary w-100" {{action "login_azure" }}>
<svg id="bdb56329-4717-4410-aa13-4505ecaa4e46" xmlns="http://www.w3.org/2000/svg" width="18" height="18"
viewBox="0 0 18 18">
<defs>
<linearGradient id="ba2610c3-a45a-4e7e-a0c0-285cfd7e005d" x1="13.25" y1="13.02" x2="8.62"
y2="4.25" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#1988d9" />
<stop offset="0.9" stop-color="#54aef0" />
</linearGradient>
<linearGradient id="bd8f618b-4f2f-4cb7-aff0-2fd2d211326d" x1="11.26" y1="10.47" x2="14.46"
y2="15.99" gradientUnits="userSpaceOnUse">
<stop offset="0.1" stop-color="#54aef0" />
<stop offset="0.29" stop-color="#4fabee" />
<stop offset="0.51" stop-color="#41a2e9" />
<stop offset="0.74" stop-color="#2a93e0" />
<stop offset="0.88" stop-color="#1988d9" />
</linearGradient>
</defs>
<title>Icon-identity-221</title>
<polygon points="1.01 10.19 8.93 15.33 16.99 10.17 18 11.35 8.93 17.19 0 11.35 1.01 10.19"
fill="#50e6ff" />
<polygon points="1.61 9.53 8.93 0.81 16.4 9.54 8.93 14.26 1.61 9.53" fill="#fff" />
<polygon points="8.93 0.81 8.93 14.26 1.61 9.53 8.93 0.81" fill="#50e6ff" />
<polygon points="8.93 0.81 8.93 14.26 16.4 9.54 8.93 0.81"
fill="url(#ba2610c3-a45a-4e7e-a0c0-285cfd7e005d)" />
<polygon points="8.93 7.76 16.4 9.54 8.93 14.26 8.93 7.76" fill="#53b1e0" />
<polygon points="8.93 14.26 1.61 9.53 8.93 7.76 8.93 14.26" fill="#9cebff" />
<polygon points="8.93 17.19 18 11.35 16.99 10.17 8.93 15.33 8.93 17.19"
fill="url(#bd8f618b-4f2f-4cb7-aff0-2fd2d211326d)" />
</svg> Sign in with Azure AD
</button>
</div>
{{/if}}

</div>
</div>
31 changes: 31 additions & 0 deletions webapp/app/setup/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,37 @@
{{/if}}


</div>

<div class="form-group">

<div class="checkbox">
<label>
{{input type="checkbox" id="social-azure-enable" checked=config.azure_oauth2_enabled}}
Enable Azure AD OAuth2 Authentication
</label>
</div>

{{#if config.azure_oauth2_enabled}}
<div class="form-group">
<label class="control-label" for="azure-oauth2-client-id">OAuth2 Client ID</label>
{{input class="form-control" id="azure-oauth2-client-id" value=config.azure_oauth2_client_id placeholder="XXXXXX" required=true}}
</div>

<div class="form-group">
<label class="control-label" for="azure-oauth2-client-secret">OAuth2 Client Secret</label>
{{input class="form-control" id="azure-oauth2-client-secret" value=config.azure_oauth2_client_secret placeholder="XXXXXX" required=true}}
</div>

<div class="form-group">
<label class="control-label" for="azure-oauth2-tenant-id">OAuth2 Tenant ID</label>
{{input class="form-control" id="azure-oauth2-tenant-id" value=config.azure_oauth2_tenant_id placeholder="XXXXXX" required=true}}
</div>

<p class="help-block">Can be obtained from <a href="https://portal.azure.com/">the Azure Developer Console</a></p>
{{/if}}


</div>

<div class="form-group">
Expand Down
13 changes: 10 additions & 3 deletions webapp/config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,16 @@ module.exports = function(environment) {
'google-oauth2': {
// redirectUri is assigned in app.js...
apiKey: null,
scope: 'email profile'
}
}
scope: 'email profile',
allowUnsafeRedirect: true
},
'azure-ad2-oauth2': {
tenantId: null,
apiKey: null,
scope: "openid profile email user.read",
allowUnsafeRedirect: true,
}
}
}
};

Expand Down
1 change: 1 addition & 0 deletions webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"sass": "^1.17.3",
"showdown": "^1.6.4",
"torii": "^0.10.1",
"torii-azure-ad2-provider": "^1.0.5",
"twix": "^1.2.1"
},
"engines": {
Expand Down
Loading