def create_user_info(client, user, scope_set, id_token=False): '''Create user info dictionnary''' user_info = {'sub': make_sub(client, user)} attributes = get_attributes({ 'user': user, 'request': None, 'service': client, '__wanted_attributes': client.get_wanted_attributes() }) for claim in client.oidcclaim_set.filter(name__isnull=False): if not set(claim.get_scopes()).intersection(scope_set): continue if not claim.value in attributes: continue user_info[claim.name] = normalize_claim_values(attributes[claim.value]) # check if attribute is verified if claim.value + ':verified' in attributes: user_info[claim.value + '_verified'] = True hooks.call_hooks('idp_oidc_modify_user_info', client, user, scope_set, user_info) return user_info
def form_valid(self, form): response = super(RoleDeleteView, self).form_valid(form) hooks.call_hooks('event', name='manager-delete-role', user=self.request.user, role=form.instance) return response
def form_valid(self, form): RoleParenting = get_role_parenting_model() role = form.cleaned_data['role'] action = form.cleaned_data['action'] if self.can_change: if action == 'add': if RoleParenting.objects.filter(parent=self.object, child=role, direct=True).exists(): messages.warning( self.request, _('Role "%s" is already a ' 'child of this role.') % role.name) else: self.object.add_child(role) hooks.call_hooks('event', name='manager-add-child-role', user=self.request.user, parent=self.object, child=role) elif action == 'remove': hooks.call_hooks('event', name='manager-remove-child-role', user=self.request.user, parent=self.object, child=role) self.object.remove_child(role) else: messages.warning(self.request, _('You are not authorized')) return super(RoleChildrenView, self).form_valid(form)
def form_valid(self, form): user = form.cleaned_data['user'] action = form.cleaned_data['action'] if self.can_change: if action == 'add': if self.object.members.filter(pk=user.pk).exists(): messages.warning(self.request, _('User already in this role.')) else: self.object.members.add(user) hooks.call_hooks('event', name='manager-add-role-member', user=self.request.user, role=self.object, member=user) elif action == 'remove': if not self.object.members.filter(pk=user.pk).exists(): messages.warning(self.request, _('User was not in this role.')) else: self.object.members.remove(user) hooks.call_hooks('event', name='manager-remove-role-member', user=self.request.user, role=self.object, member=user) else: messages.warning(self.request, _('You are not authorized')) return super(RoleMembersView, self).form_valid(form)
def form_valid(self, form): response = super(RoleAddView, self).form_valid(form) hooks.call_hooks('event', name='manager-add-role', user=self.request.user, instance=form.instance, form=form) return response
def post(self, request, *args, **kwargs): self.object.get_admin_role().members.remove(self.user) hooks.call_hooks('event', name='remove-remove-admin-role-user', user=self.request.user, role=self.object, admin=self.user) return redirect(self.request, self.success_url)
def post(self, request, *args, **kwargs): self.object.get_admin_role().remove_child(self.child) hooks.call_hooks('event', name='manager-remove-admin-role', user=self.request.user, role=self.object, admin_role=self.child) return redirect(self.request, self.success_url)
def post(self, request, *args, **kwargs): self.object.remove_child(self.child) hooks.call_hooks('event', name='manager-remove-child-role', user=self.request.user, parent=self.object, child=self.child) return redirect(self.request, self.success_url)
def form_valid(self, form): administered_role = self.get_object() for user in form.cleaned_data['users']: administered_role.get_admin_role().members.add(user) hooks.call_hooks('event', name='manager-add-admin-role-user', user=self.request.user, role=administered_role, admin=user) return super(RoleAddAdminUserView, self).form_valid(form)
def form_valid(self, form): administered_role = self.get_object() for role in form.cleaned_data['roles']: administered_role.get_admin_role().add_child(role) hooks.call_hooks('event', name='manager-add-admin-role', user=self.request.user, role=administered_role, admin_role=role) return super(RoleAddAdminRoleView, self).form_valid(form)
def post(self, request, *args, **kwargs): if not self.request.user.has_perm('a2_rbac.change_role', self.parent): raise PermissionDenied self.object.remove_parent(self.parent) hooks.call_hooks('event', name='manager-remove-child-role', user=self.request.user, parent=self.parent, child=self.object) return redirect(self.request, self.success_url)
def form_valid(self, form): child = self.get_object() for role in form.cleaned_data['roles']: child.add_parent(role) hooks.call_hooks('event', name='manager-add-child-role', user=self.request.user, parent=role, child=child) return super(RoleAddParentView, self).form_valid(form)
def get_displayed_other_actions(self): actions = [] other_actions = list(self.get_other_actions()) hooks.call_hooks('manager_modify_other_actions', self, other_actions) for action in other_actions: if callable(action.display) and not action.display( self.object, self.request): continue if action.display: actions.append(action) return actions
def form_valid(self, form): models.DeletedUser.objects.delete_user(self.request.user) self.request.user.email += '#%d' % random.randint(1, 10000000) self.request.user.email_verified = False self.request.user.save(update_fields=['email', 'email_verified']) logger.info(u'deletion of account %s requested', self.request.user) hooks.call_hooks('event', name='delete-account', user=self.request.user) messages.info( self.request, _('Your account has been scheduled for deletion. You cannot use it anymore.' )) return super(DeleteView, self).form_valid(form)
def get(self, request): '''Continue CAS login after authentication''' service = request.GET.get(SERVICE_PARAM) ticket_id = request.GET.get(NONCE_FIELD_NAME) cancel = request.GET.get(CANCEL_PARAM) is not None if ticket_id is None: return self.failure(request, service, 'missing ticket id') if not ticket_id.startswith(SERVICE_TICKET_PREFIX): return self.failure(request, service, 'invalid ticket id') try: st = Ticket.objects.select_related('service', 'user').get(ticket_id=ticket_id) except Ticket.DoesNotExist: return self.failure(request, service, 'unknown ticket id') # no valid ticket should be submitted to continue, delete them ! if st.valid(): st.delete() return self.failure( request, service, 'ticket %r already valid passed to continue' % st.ticket_id) # service URL mismatch if st.service_url != service: st.delete() return self.failure( request, service, 'ticket service does not match service parameter') # user asked for cancellation if cancel: st.delete() self.logger.debug('login from %s canceled', service) return redirect(request, service) # Not logged in ? Authenticate again if not request.user.is_authenticated(): return self.authenticate(request, st) # Renew requested and ticket is unknown ? Try again if st.renew and not find_authentication_event(request, st.ticket_id): return self.authenticate(request, st) # if user not authorized, a ServiceAccessDenied exception # is raised and handled by ServiceAccessMiddleware st.service.authorize(request.user) self.validate_ticket(request, st) if st.valid(): hooks.call_hooks('event', name='sso-success', service=st.service, user=st.user) return redirect(request, service, params={'ticket': st.ticket_id}) # Should not happen assert False
def registration_success(self, request, user, form): hooks.call_hooks('event', name='registration', user=user, form=form, view=self, authentication_method=self.authentication_method, token=request.token, service=self.service) simulate_authentication(request, user, method=self.authentication_method, service_slug=self.service) messages.info(self.request, _('You have just created an account.')) self.send_registration_success_email(user) return redirect(request, self.get_success_url())
def get(self, request): service = request.GET.get(SERVICE_PARAM) renew = request.GET.get(RENEW_PARAM) is not None gateway = request.GET.get(GATEWAY_PARAM) is not None if not service: return self.failure(request, '', 'no service field') model = Service.objects.for_service(service) if not model: return self.failure(request, service, 'service unknown') if renew and gateway: return self.failure( request, service, 'renew and gateway cannot be requested ' 'at the same time') hooks.call_hooks('event', name='sso-request', service=model) st = Ticket() st.service = model # Limit size of return URL to an acceptable length service = service[:4096] st.service_url = service st.renew = renew self.logger.debug('login request from %r renew: %s gateway: %s', service, renew, gateway) if self.must_authenticate(request, renew, gateway): st.save() return self.authenticate(request, st) self.validate_ticket(request, st) if st.valid(): st.save() hooks.call_hooks('event', name='sso-success', service=model, user=request.user) return redirect(request, service, params={'ticket': st.ticket_id}) self.logger.debug('gateway requested but no session is open') return redirect(request, service)
def form_valid(self, form): if self.can_change: operation = form.cleaned_data.get('operation') ou = form.cleaned_data.get('ou') target = form.cleaned_data.get('target') action = form.cleaned_data.get('action') Permission = get_permission_model() if action == 'add' and operation and target: perm, created = Permission.objects \ .get_or_create(operation=operation, ou=ou, target_ct=ContentType.objects.get_for_model( target), target_id=target.pk) self.object.permissions.add(perm) hooks.call_hooks('event', name='manager-add-permission', user=self.request.user, role=self.object, permission=perm) elif action == 'remove': try: permission_id = int(self.request.POST.get( 'permission', '')) perm = Permission.objects.get(id=permission_id) except (ValueError, Permission.DoesNotExist): pass else: if self.object.permissions.filter( id=permission_id).exists(): self.object.permissions.remove(perm) hooks.call_hooks('event', name='manager-remove-permission', user=self.request.user, role=self.object, permission=perm) else: messages.warning(self.request, _('You are not authorized')) return super(RolePermissionsView, self).form_valid(form)
def post(self, request, *args, **kwargs): self.object = self.get_object() for action in self.get_displayed_other_actions(): if action.name in request.POST: response = None if hasattr(action, 'do'): response = action.do(self, request, self.object) else: method = getattr(self, 'action_' + action.name, None) if method: response = method(request, *args, **kwargs) hooks.call_hooks('event', name='manager-action', user=self.request.user, action=action, instance=self.object) if response: return response self.request.method = 'GET' return self.get(request, *args, **kwargs) parent = super(OtherActionsMixin, self) if hasattr(parent, 'post'): return parent.post(request, *args, **kwargs) return self.get(request, *args, **kwargs)
def get_homepage_entries(self): entries = [] for entry in self.default_entries: if 'permission' in entry and not self.request.user.has_perm_any( entry['permission']): continue entries.append(entry) for hook_entries in hooks.call_hooks('manager_homepage_entries', self): if not hasattr(hook_entries, 'append'): hook_entries = [hook_entries] for entry in hook_entries: if 'permission' in entry and not self.request.user.has_perm_any( entry['permission']): continue entries.append(entry) # use possible key order to sort # list.sort() is supposed to be a stable sort (already sorted entries # are kept in the same order) entries.sort(key=lambda d: d.get('order', 0)) return entries
def get_form(self, form_class=None): form = super(RegistrationCompletionView, self).get_form(form_class=form_class) hooks.call_hooks('front_modify_form', self, form) return form
def authorize(request, *args, **kwargs): logger = logging.getLogger(__name__) start = now() try: client_id = request.GET['client_id'] redirect_uri = request.GET['redirect_uri'] except KeyError as k: return HttpResponseBadRequest('invalid request: missing parameter %s' % k.args[0], content_type='text/plain') try: client = models.OIDCClient.objects.get(client_id=client_id) except models.OIDCClient.DoesNotExist: return HttpResponseBadRequest('invalid request: unknown client_id', content_type='text/plain') fragment = client.authorization_flow == client.FLOW_IMPLICIT state = request.GET.get('state') try: response_type = request.GET['response_type'] scope = request.GET['scope'] except KeyError as k: return authorization_error(request, redirect_uri, 'invalid_request', state=state, error_description='missing parameter %s' % k.args[0], fragment=fragment) prompt = set(filter(None, request.GET.get('prompt', '').split())) nonce = request.GET.get('nonce') scopes = utils.scope_set(scope) max_age = request.GET.get('max_age') if max_age: try: max_age = int(max_age) if max_age < 0: raise ValueError except ValueError: return authorization_error(request, redirect_uri, 'invalid_request', error_description='max_age is not a positive integer', state=state, fragment=fragment) if redirect_uri not in client.redirect_uris.split(): return authorization_error(request, redirect_uri, 'invalid_request', error_description='unauthorized redirect_uri', state=state, fragment=fragment) if client.authorization_flow == client.FLOW_AUTHORIZATION_CODE: if response_type != 'code': return authorization_error(request, redirect_uri, 'unsupported_response_type', error_description='only code is supported', state=state, fragment=fragment) elif client.authorization_flow == client.FLOW_IMPLICIT: if not set(filter(None, response_type.split())) in (set(['id_token', 'token']), set(['id_token'])): return authorization_error(request, redirect_uri, 'unsupported_response_type', error_description='only "id_token token" or "id_token" ' 'are supported', state=state, fragment=fragment) else: raise NotImplementedError if 'openid' not in scopes: return authorization_error(request, redirect_uri, 'invalid_request', error_description='openid scope is missing', state=state, fragment=fragment) allowed_scopes = app_settings.SCOPES or ['openid', 'email', 'profile'] if not (scopes <= set(allowed_scopes)): message = 'only "%s" scope(s) are supported, but "%s" requested' % ( ', '.join(allowed_scopes), ', '.join(scopes)) return authorization_error(request, redirect_uri, 'invalid_scope', error_description=message, state=state, fragment=fragment) hooks.call_hooks('event', name='sso-request', idp='oidc', service=client) # authentication canceled by user if 'cancel' in request.GET: logger.info(u'authentication canceled for service %s', client.name) return authorization_error(request, redirect_uri, 'access_denied', error_description='user did not authenticate', state=state, fragment=fragment) if not request.user.is_authenticated() or 'login' in prompt: if 'none' in prompt: return authorization_error(request, redirect_uri, 'login_required', error_description='login is required but prompt is none', state=state, fragment=fragment) params = {} if nonce is not None: params['nonce'] = nonce return login_require(request, params=params, service=client) # if user not authorized, a ServiceAccessDenied exception # is raised and handled by ServiceAccessMiddleware client.authorize(request.user) last_auth = last_authentication_event(request.session) if max_age is not None and time.time() - last_auth['when'] >= max_age: if 'none' in prompt: return authorization_error(request, redirect_uri, 'login_required', error_description='login is required but prompt is none', state=state, fragment=fragment) params = {} if nonce is not None: params['nonce'] = nonce return login_require(request, params=params, service=client) if client.authorization_mode != client.AUTHORIZATION_MODE_NONE or 'consent' in prompt: # authorization by user is mandatory, as per local configuration or per explicit request by # the RP if client.authorization_mode in (client.AUTHORIZATION_MODE_NONE, client.AUTHORIZATION_MODE_BY_SERVICE): auth_manager = client.authorizations elif client.authorization_mode == client.AUTHORIZATION_MODE_BY_OU: auth_manager = client.ou.oidc_authorizations qs = auth_manager.filter(user=request.user) if 'consent' in prompt: # if consent is asked we delete existing authorizations # it seems to be the safer option qs.delete() qs = auth_manager.none() else: qs = qs.filter(expired__gte=start) authorized_scopes = set() for authorization in qs: authorized_scopes |= authorization.scope_set() if (authorized_scopes & scopes) < scopes: if 'none' in prompt: return authorization_error( request, redirect_uri, 'consent_required', error_description='consent is required but prompt is none', state=state, fragment=fragment) if request.method == 'POST': if 'accept' in request.POST: pk_to_deletes = [] for authorization in qs: # clean obsolete authorizations if authorization.scope_set() <= scopes: pk_to_deletes.append(authorization.pk) auth_manager.create( user=request.user, scopes=u' '.join(sorted(scopes)), expired=start + datetime.timedelta(days=365)) if pk_to_deletes: auth_manager.filter(pk__in=pk_to_deletes).delete() logger.info(u'authorized scopes %s for service %s', ' '.join(scopes), client.name) else: logger.info(u'refused scopes %s for service %s', ' '.join(scopes), client.name) return authorization_error(request, redirect_uri, 'access_denied', error_description='user denied access', state=state, fragment=fragment) else: return render(request, 'authentic2_idp_oidc/authorization.html', { 'client': client, 'scopes': scopes - set(['openid']), }) if response_type == 'code': code = models.OIDCCode.objects.create( client=client, user=request.user, scopes=u' '.join(scopes), state=state, nonce=nonce, redirect_uri=redirect_uri, expired=start + datetime.timedelta(seconds=30), auth_time=datetime.datetime.fromtimestamp(last_auth['when'], utc), session_key=request.session.session_key) logger.info(u'sending code %s for scopes %s for service %s', code.uuid, ' '.join(scopes), client.name) params = { 'code': unicode(code.uuid), } if state is not None: params['state'] = state response = redirect(request, redirect_uri, params=params, resolve=False) else: # FIXME: we should probably factorize this part with the token endpoint similar code need_access_token = 'token' in response_type.split() expires_in = 3600 * 8 if need_access_token: access_token = models.OIDCAccessToken.objects.create( client=client, user=request.user, scopes=u' '.join(scopes), session_key=request.session.session_key, expired=start + datetime.timedelta(seconds=expires_in)) acr = '0' if nonce is not None and last_auth.get('nonce') == nonce: acr = '1' id_token = utils.create_user_info(client, request.user, scopes, id_token=True) id_token.update({ 'iss': utils.get_issuer(request), 'aud': client.client_id, 'exp': timestamp_from_datetime(start + idtoken_duration(client)), 'iat': timestamp_from_datetime(start), 'auth_time': last_auth['when'], 'acr': acr, 'sid': utils.get_session_id(request, client), }) if nonce is not None: id_token['nonce'] = nonce params = { 'id_token': utils.make_idtoken(client, id_token), } if state is not None: params['state'] = state if need_access_token: params.update({ 'access_token': access_token.uuid, 'token_type': 'Bearer', 'expires_in': expires_in, }) # query is transfered through the hashtag response = redirect(request, redirect_uri + '#%s' % urlencode(params), resolve=False) hooks.call_hooks('event', name='sso-success', idp='oidc', service=client, user=request.user) utils.add_oidc_session(request, client) return response
def get_context_data(self, **kwargs): form = self.get_form() hooks.call_hooks('manager_modify_form', self, form) kwargs['form'] = form ctx = super(BaseDetailView, self).get_context_data(**kwargs) return ctx
def get_form(self, form_class=None): form = super(ModelFormView, self).get_form(form_class=form_class) hooks.call_hooks('manager_modify_form', self, form) return form
def get_table(self, **kwargs): table = super(TableHookMixin, self).get_table(**kwargs) import copy table = copy.deepcopy(table) hooks.call_hooks('manager_modify_table', self, table) return table