|
| 1 | +""" |
| 2 | +Backend for OpenID Connect EGI Check-in |
| 3 | +https://www.egi.eu/service/check-in/ |
| 4 | +""" |
| 5 | + |
| 6 | +from social_core.backends.open_id_connect import OpenIdConnectAuth |
| 7 | + |
| 8 | +CHECKIN_ENV_ENDPOINTS = { |
| 9 | + "prod": "https://aai.egi.eu/auth/realms/egi", |
| 10 | + "demo": "https://aai-demo.egi.eu/auth/realms/egi", |
| 11 | + "dev": "https://aai-dev.egi.eu/auth/realms/egi", |
| 12 | +} |
| 13 | + |
| 14 | + |
| 15 | +class EGICheckinOpenIdConnect(OpenIdConnectAuth): |
| 16 | + name = "egi-checkin" |
| 17 | + # Check-in provides 3 environments: production, demo and development |
| 18 | + # Set the one to use as "prod", "demo" or "dev" |
| 19 | + CHECKIN_ENV = "prod" |
| 20 | + # This is a opaque and unique id for every user that looks like an email |
| 21 | + # see https://docs.egi.eu/providers/check-in/sp/#1-community-user-identifier |
| 22 | + USERNAME_KEY = "voperson_id" |
| 23 | + EXTRA_DATA = [ |
| 24 | + ("expires_in", "expires_in", True), |
| 25 | + ("refresh_token", "refresh_token", True), |
| 26 | + ("id_token", "id_token", True), |
| 27 | + ] |
| 28 | + # In order to get any scopes, you have to register your service with |
| 29 | + # Check-in, see documentation at https://docs.egi.eu/providers/check-in/sp/ |
| 30 | + DEFAULT_SCOPE = [ |
| 31 | + "openid", |
| 32 | + "profile", |
| 33 | + "email", |
| 34 | + "voperson_id", |
| 35 | + "eduperson_entitlement", |
| 36 | + "offline_access", |
| 37 | + ] |
| 38 | + # This is the list of entitlements that are allowed to login into the |
| 39 | + # service. A user with any of these will be allowed. If empty, all |
| 40 | + # users will be allowed |
| 41 | + ALLOWED_ENTITLEMENTS = [] |
| 42 | + |
| 43 | + def oidc_endpoint(self): |
| 44 | + endpoint = self.setting("OIDC_ENDPOINT", self.OIDC_ENDPOINT) |
| 45 | + if endpoint: |
| 46 | + return endpoint |
| 47 | + checkin_env = self.setting("CHECKIN_ENV", self.CHECKIN_ENV) |
| 48 | + return CHECKIN_ENV_ENDPOINTS.get(checkin_env, "") |
| 49 | + |
| 50 | + def get_user_details(self, response): |
| 51 | + username_key = self.setting("USERNAME_KEY", default=self.USERNAME_KEY) |
| 52 | + fullname, first_name, last_name = self.get_user_names( |
| 53 | + response.get("name") or "", |
| 54 | + response.get("given_name") or "", |
| 55 | + response.get("family_name") or "", |
| 56 | + ) |
| 57 | + return { |
| 58 | + "username": response.get(username_key), |
| 59 | + "email": response.get("email"), |
| 60 | + "fullname": fullname, |
| 61 | + "first_name": first_name, |
| 62 | + "last_name": last_name, |
| 63 | + } |
| 64 | + |
| 65 | + def entitlement_allowed(self, user_entitlements): |
| 66 | + allowed = True |
| 67 | + allowed_ent = self.setting("ALLOWED_ENTITLEMENTS", self.ALLOWED_ENTITLEMENTS) |
| 68 | + if allowed_ent: |
| 69 | + allowed = any(e in user_entitlements for e in allowed_ent) |
| 70 | + return allowed |
| 71 | + |
| 72 | + def auth_allowed(self, response, details): |
| 73 | + """Check-in promotes the use of eduperson_entitlements for AuthZ, if |
| 74 | + ALLOWED_ENTITLEMENTS is defined then use them to allow or not users""" |
| 75 | + allowed = super().auth_allowed(response, details) |
| 76 | + if allowed: |
| 77 | + user_entitlements = response.get("eduperson_entitlement") or [] |
| 78 | + allowed = self.entitlement_allowed(user_entitlements) |
| 79 | + return allowed |
0 commit comments