diff --git a/docker/lifemonitor.Dockerfile b/docker/lifemonitor.Dockerfile index ed6bfe018..55f9b0acd 100644 --- a/docker/lifemonitor.Dockerfile +++ b/docker/lifemonitor.Dockerfile @@ -94,6 +94,9 @@ COPY --chown=lm:lm lifemonitor /lm/lifemonitor COPY --chown=lm:lm migrations /lm/migrations COPY --chown=lm:lm cli /lm/cli +# Ensure read access to source code to unprivileged users +RUN find /lm/lifemonitor/ -type d -exec chmod a+r {} \; + ################################################################## ## Node Stage ################################################################## diff --git a/k8s/Chart.yaml b/k8s/Chart.yaml index b5ab493a6..1ae3d21f0 100644 --- a/k8s/Chart.yaml +++ b/k8s/Chart.yaml @@ -12,7 +12,7 @@ version: 0.12.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 0.13.2 +appVersion: 0.14.0 # Chart dependencies dependencies: diff --git a/lifemonitor/auth/oauth2/client/controllers.py b/lifemonitor/auth/oauth2/client/controllers.py index ad0e37c29..d21273da0 100644 --- a/lifemonitor/auth/oauth2/client/controllers.py +++ b/lifemonitor/auth/oauth2/client/controllers.py @@ -86,8 +86,15 @@ def authorize(name): user_info = remote.userinfo(token=token) return _handle_authorize(remote, token, user_info) except OAuthError as e: - logger.debug(e) - return e.description, 401 + if logger.isEnabledFor(logging.DEBUG): + logger.exception(e) + raise exceptions.OAuthAuthorizationException(title="Authorization Error", + detail=e.description) + except Exception as e: + if logger.isEnabledFor(logging.DEBUG): + logger.exception(e) + raise exceptions.OAuthAuthorizationException(title="Authorization Error", + detail="Unable to authorize the user") @blueprint.route('/login/') @next_route_aware diff --git a/lifemonitor/auth/oauth2/client/models.py b/lifemonitor/auth/oauth2/client/models.py index 1d2f245a5..1643d2ab4 100644 --- a/lifemonitor/auth/oauth2/client/models.py +++ b/lifemonitor/auth/oauth2/client/models.py @@ -126,6 +126,7 @@ def to_dict(self): @staticmethod def from_dict(data: dict): + assert data, "User data from the OAuth Provider cannot be empty" profile = OAuthUserProfile() for k, v, in data.items(): setattr(profile, k, v) diff --git a/lifemonitor/auth/oauth2/client/providers/lsaai.py b/lifemonitor/auth/oauth2/client/providers/lsaai.py index 27681a237..55526b449 100644 --- a/lifemonitor/auth/oauth2/client/providers/lsaai.py +++ b/lifemonitor/auth/oauth2/client/providers/lsaai.py @@ -21,7 +21,7 @@ import logging from flask import current_app - +from lifemonitor.exceptions import OAuthAuthorizationException from lifemonitor.auth.oauth2.client.models import OAuthIdentity # Config a module level logger @@ -29,33 +29,18 @@ def normalize_userinfo(client, data): - logger.debug("LSAAI Data: %r", data) - preferred_username = data.get('eduperson_principal_name')[0].replace('@lifescience-ri.eu', '') \ - if 'eduperson_principal_namex' in data and len(data['eduperson_principal_name']) > 0 \ - else data['name'].replace(' ', '') - params = { - 'sub': str(data['sub']), - 'name': data['name'], - 'email': data.get('email'), - 'preferred_username': preferred_username - # 'profile': data['html_url'], - # 'picture': data['avatar_url'], - # 'website': data.get('blog'), - } - - # The email can be be None despite the scope being 'user:email'. - # That is because a user can choose to make his/her email private. - # If that is the case we get all the users emails regardless if private or note - # and use the one he/she has marked as `primary` + info = {} try: - if params.get('email') is None: - resp = client.get('user/emails') - resp.raise_for_status() - data = resp.json() - params["email"] = next(email['email'] for email in data if email['primary']) - except Exception as e: - logger.warning("Unable to get user email. Reason: %r", str(e)) - return params + info["sub"] = data['sub'] + except KeyError: + raise OAuthAuthorizationException(title="Unable to get user data", + description="the LS ID is required") + for key in ['name', 'email', 'preferred_username']: + info[key] = data.get(key, None) + if info[key] is None: + logger.warning("User %r has no %r", info["sub"], key) + + return info class LsAAI: @@ -65,15 +50,15 @@ class LsAAI: 'client_id': current_app.config.get('LSAAI_CLIENT_ID', None), 'client_secret': current_app.config.get('LSAAI_CLIENT_SECRET', None), 'client_name': client_name, - 'uri': 'https://proxy.aai.lifescience-ri.eu', - 'api_base_url': 'https://proxy.aai.lifescience-ri.eu', - 'access_token_url': 'https://proxy.aai.lifescience-ri.eu/OIDC/token', - 'authorize_url': 'https://proxy.aai.lifescience-ri.eu/saml2sp/OIDC/authorization', - 'client_kwargs': {'scope': 'openid profile email orcid eduperson_principal_name'}, - 'userinfo_endpoint': 'https://proxy.aai.lifescience-ri.eu/OIDC/userinfo', + 'uri': 'https://login.aai.lifescience-ri.eu', + 'api_base_url': 'https://login.aai.lifescience-ri.eu', + 'access_token_url': 'https://login.aai.lifescience-ri.eu/oidc/token', + 'authorize_url': 'https://login.aai.lifescience-ri.eu/oidc/authorize', + 'client_kwargs': {'scope': 'openid profile email'}, + 'userinfo_endpoint': 'https://login.aai.lifescience-ri.eu/oidc/userinfo', 'userinfo_compliance_fix': normalize_userinfo, 'user_profile_html': 'https://profile.aai.lifescience-ri.eu/profile', - 'server_metadata_url': 'https://proxy.aai.lifescience-ri.eu/.well-known/openid-configuration' + 'server_metadata_url': 'https://login.aai.lifescience-ri.eu/oidc/.well-known/openid-configuration' } def __repr__(self) -> str: diff --git a/lifemonitor/auth/templates/auth/identity_not_found.j2 b/lifemonitor/auth/templates/auth/identity_not_found.j2 index 121fbe04b..6a518306f 100644 --- a/lifemonitor/auth/templates/auth/identity_not_found.j2 +++ b/lifemonitor/auth/templates/auth/identity_not_found.j2 @@ -6,10 +6,10 @@ {% block body %}
- + {{ macros.render_logo(class="login-logo", style="width: auto") }} -
+
{{ macros.render_provider_logo(identity.provider) }}
@@ -35,7 +39,7 @@ If you already have an account, we strongly recommend that you Sign In with your existing credentials and link your new identity - from the account configuration page. + from the account configuration page.

- OR -

@@ -43,18 +47,18 @@ linked to your {{ identity.provider.name }} identity.

-
+
{% endif %}
{{ form.hidden_tag() }} -
+ -{% endblock body %} \ No newline at end of file +{% endblock body %} diff --git a/lifemonitor/auth/templates/auth/register.j2 b/lifemonitor/auth/templates/auth/register.j2 index 0d495f2a2..5913d424a 100644 --- a/lifemonitor/auth/templates/auth/register.j2 +++ b/lifemonitor/auth/templates/auth/register.j2 @@ -6,10 +6,10 @@ {% block body %}