def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None g.usersession = None if 'sessionid' in session: usersession = UserSession.authenticate(buid=session['sessionid']) g.usersession = usersession if usersession: usersession.access() db.session.commit() # Save access g.user = usersession.user else: session.pop('sessionid', None) # Transition users with 'userid' to 'sessionid' if 'userid' in session: if not g.usersession: user = User.get(userid=session['userid']) if user: usersession = UserSession(user=user) usersession.access() db.session.commit() # Save access g.usersession = usersession g.user = user session['sessionid'] = usersession.buid session.pop('userid', None) # This will be set to True downstream by the requires_login decorator g.login_required = False
def permission_user_delete(client, kwargs): if client.user: user = User.get(buid=kwargs['buid']) if not user: abort(404) permassign = UserClientPermissions.query.filter_by( user=user, client=client).first_or_404() return render_delete_sqla( permassign, db, title=_(u"Confirm delete"), message= _(u"Remove all permissions assigned to user {pname} for app ‘{title}’?" ).format(pname=user.pickername, title=client.title), success=_(u"You have revoked permisions for user {pname}").format( pname=user.pickername), next=url_for('.client_info', key=client.key)) else: team = Team.get(buid=kwargs['buid']) if not team: abort(404) permassign = TeamClientPermissions.query.filter_by( team=team, client=client).first_or_404() return render_delete_sqla( permassign, db, title=_(u"Confirm delete"), message= _(u"Remove all permissions assigned to team ‘{pname}’ for app ‘{title}’?" ).format(pname=team.title, title=client.title), success=_(u"You have revoked permisions for team {title}").format( title=team.title), next=url_for('.client_info', key=client.key))
def user_get_by_userid(): """ Returns user or organization with the given userid (Lastuser internal userid) """ userid = request.values.get('userid') if not userid: return api_result('error', error='no_userid_provided') user = User.get(userid=userid, defercols=True) if user: return api_result('ok', type='user', userid=user.userid, buid=user.userid, name=user.username, title=user.fullname, label=user.pickername, timezone=user.timezone, oldids=[o.userid for o in user.oldids]) else: org = Organization.get(userid=userid, defercols=True) if org: return api_result('ok', type='organization', userid=org.userid, buid=org.userid, name=org.name, title=org.title, label=org.pickername) return api_result('error', error='not_found')
def account_merge(): if 'merge_buid' not in session: return redirect(get_next_url(), code=302) other_user = User.get(buid=session['merge_buid']) if other_user is None: session.pop('merge_buid', None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if 'merge' in request.form: new_user = merge_users(current_auth.user, other_user) login_internal(new_user) flash(_("Your accounts have been merged"), 'success') session.pop('merge_buid', None) db.session.commit() user_data_changed.send(new_user, changes=['merge']) return redirect(get_next_url(), code=303) else: session.pop('merge_buid', None) return redirect(get_next_url(), code=303) return render_template( 'merge.html.jinja2', form=form, user=current_auth.user, other_user=other_user, login_registry=login_registry, )
def permission_user_edit(client, kwargs): if client.user: user = User.get(userid=kwargs['userid']) if not user: abort(404) available_perms = Permission.query.filter( db.or_(Permission.allusers == True, Permission.user == g.user)).order_by('name').all() permassign = UserClientPermissions.query.filter_by( user=user, client=client).first_or_404() elif client.org: team = Team.get(userid=kwargs['userid']) if not team: abort(404) available_perms = Permission.query.filter( db.or_(Permission.allusers == True, Permission.org == client.org)).order_by('name').all() permassign = TeamClientPermissions.query.filter_by( team=team, client=client).first_or_404() form = PermissionEditForm() form.perms.choices = [(ap.name, u"{name} – {title}".format(name=ap.name, title=ap.title)) for ap in available_perms] if request.method == 'GET': if permassign: form.perms.data = permassign.access_permissions.split(u' ') if form.validate_on_submit(): form.perms.data.sort() perms = u' '.join(form.perms.data) if not perms: db.session.delete(permassign) else: permassign.access_permissions = perms db.session.commit() if perms: if client.user: flash( u"Permissions have been updated for user {pname}".format( pname=user.pickername), 'success') else: flash( u"Permissions have been updated for team {title}".format( title=team.title), 'success') else: if client.user: flash( u"All permissions have been revoked for user {pname}". format(pname=user.pickername), 'success') else: flash( u"All permissions have been revoked for team {title}". format(title=team.title), 'success') return render_redirect(url_for('.client_info', key=client.key), code=303) return render_form(form=form, title="Edit permissions", formid="perm_edit", submit="Save changes", ajax=True)
def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None if 'userid' in session: g.user = User.get(userid=session['userid'])
def validate_username(self, field): if field.data in current_app.config['RESERVED_USERNAMES']: raise wtforms.ValidationError, "This name is reserved" if not valid_username(field.data): raise wtforms.ValidationError(u"Invalid characters in name. Names must be made of ‘a-z’, ‘0-9’ and ‘-’, without trailing dashes") existing = User.get(username=field.data) if existing is not None: raise wtforms.ValidationError("This username is taken")
def validate_username(self, field): if field.data in current_app.config['RESERVED_USERNAMES']: raise wtforms.ValidationError, "That name is reserved" if not valid_username(field.data): raise wtforms.ValidationError(u"Invalid characters in name. Names must be made of ‘a-z’, ‘0-9’ and ‘-’, without trailing dashes") existing = User.get(username=field.data) if existing is not None: raise wtforms.ValidationError("That username is taken")
def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None if "userid" in session: g.user = User.get(userid=session["userid"])
def _load_user(self): """ If there's a buid in the session, retrieve the user object and add to the request namespace object g. """ add_auth_attribute('user', None) add_auth_attribute('session', None) lastuser_cookie = {} lastuser_cookie_headers = { } # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: add_auth_attribute( 'session', UserSession.authenticate(buid=lastuser_cookie['sessionid'])) if current_auth.session: current_auth.session.access() db.session.commit() # Save access add_auth_attribute('user', current_auth.session.user) # Transition users with 'userid' to 'sessionid' if not current_auth.session and 'userid' in lastuser_cookie: add_auth_attribute('user', User.get(buid=lastuser_cookie['userid'])) if current_auth.is_authenticated: add_auth_attribute('session', UserSession(user=current_auth.user)) current_auth.session.access() db.session.commit() # Save access if current_auth.session: lastuser_cookie['sessionid'] = current_auth.session.buid else: lastuser_cookie.pop('sessionid', None) if current_auth.is_authenticated: lastuser_cookie['userid'] = current_auth.user.buid else: lastuser_cookie.pop('userid', None) lastuser_cookie['updated_at'] = utcnow().isoformat() add_auth_attribute('cookie', lastuser_cookie) # This will be set to True downstream by the requires_login decorator add_auth_attribute('login_required', False)
def validate_name(self, field): if not valid_username(field.data): raise wtforms.ValidationError("Invalid characters in name") if field.data in current_app.config['RESERVED_USERNAMES']: raise wtforms.ValidationError("That name is reserved") existing = User.get(username=field.data) if existing is not None: raise wtforms.ValidationError("That name is taken") existing = Organization.get(name=field.data) if existing is not None and existing.id != self.edit_id: raise wtforms.ValidationError("That name is taken")
def lookup_current_user(): """ If there's a buid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None g.usersession = None lastuser_cookie = {} lastuser_cookie_headers = { } # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: g.usersession = UserSession.authenticate( buid=lastuser_cookie['sessionid']) if g.usersession: g.usersession.access() db.session.commit() # Save access g.user = g.usersession.user # Transition users with 'userid' to 'sessionid' if not g.usersession and 'userid' in lastuser_cookie: g.user = User.get(buid=lastuser_cookie['userid']) if g.user: g.usersession = UserSession(user=g.user) g.usersession.access() db.session.commit() # Save access if g.usersession: lastuser_cookie['sessionid'] = g.usersession.buid else: lastuser_cookie.pop('sessionid', None) if g.user: lastuser_cookie['userid'] = g.user.buid else: lastuser_cookie.pop('userid', None) g.lastuser_cookie = lastuser_cookie # This will be set to True downstream by the requires_login decorator g.login_required = False
def _load_user(self): """ If there's a buid in the session, retrieve the user object and add to the request namespace object g. """ add_auth_attribute('user', None) add_auth_attribute('session', None) lastuser_cookie = {} lastuser_cookie_headers = {} # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: add_auth_attribute('session', UserSession.authenticate(buid=lastuser_cookie['sessionid'])) if current_auth.session: current_auth.session.access() db.session.commit() # Save access add_auth_attribute('user', current_auth.session.user) # Transition users with 'userid' to 'sessionid' if not current_auth.session and 'userid' in lastuser_cookie: add_auth_attribute('user', User.get(buid=lastuser_cookie['userid'])) if current_auth.is_authenticated: add_auth_attribute('session', UserSession(user=current_auth.user)) current_auth.session.access() db.session.commit() # Save access if current_auth.session: lastuser_cookie['sessionid'] = current_auth.session.buid else: lastuser_cookie.pop('sessionid', None) if current_auth.is_authenticated: lastuser_cookie['userid'] = current_auth.user.buid else: lastuser_cookie.pop('userid', None) add_auth_attribute('cookie', lastuser_cookie) # This will be set to True downstream by the requires_login decorator add_auth_attribute('login_required', False)
def lookup_current_user(): """ If there's a userid in the session, retrieve the user object and add to the request namespace object g. """ g.user = None g.usersession = None lastuser_cookie = {} lastuser_cookie_headers = {} # Ignored for now, intended for future changes # Migrate data from Flask cookie session if 'sessionid' in session: lastuser_cookie['sessionid'] = session.pop('sessionid') if 'userid' in session: lastuser_cookie['userid'] = session.pop('userid') if 'lastuser' in request.cookies: try: lastuser_cookie, lastuser_cookie_headers = lastuser_oauth.serializer.loads( request.cookies['lastuser'], return_header=True) except itsdangerous.BadSignature: lastuser_cookie = {} if 'sessionid' in lastuser_cookie: g.usersession = UserSession.authenticate(buid=lastuser_cookie['sessionid']) if g.usersession: g.usersession.access() db.session.commit() # Save access g.user = g.usersession.user # Transition users with 'userid' to 'sessionid' if not g.usersession and 'userid' in lastuser_cookie: g.user = User.get(userid=lastuser_cookie['userid']) if g.user: g.usersession = UserSession(user=g.user) g.usersession.access() db.session.commit() # Save access if g.usersession: lastuser_cookie['sessionid'] = g.usersession.buid else: lastuser_cookie.pop('sessionid', None) if g.user: lastuser_cookie['userid'] = g.user.userid else: lastuser_cookie.pop('userid', None) g.lastuser_cookie = lastuser_cookie # This will be set to True downstream by the requires_login decorator g.login_required = False
def validate_name(self, field): if not valid_username(field.data): raise forms.ValidationError(_("Invalid characters in name")) if field.data in current_app.config['RESERVED_USERNAMES']: raise forms.ValidationError(_("This name is reserved")) existing = User.get(username=field.data) if existing is not None: if existing == current_auth.user: raise forms.ValidationError(Markup(_(u"This is <em>your</em> current username. " u'You must change it first from <a href="{profile}">your profile</a> ' u"before you can assign it to an organization").format( profile=url_for('profile')))) else: raise forms.ValidationError(_("This name is taken")) existing = Organization.get(name=field.data) if existing is not None and existing.id != self.edit_id: raise forms.ValidationError(_("This name is taken"))
def permission_user_delete(client, kwargs): if client.user: user = User.get(userid=kwargs['userid']) if not user: abort(404) permassign = UserClientPermissions.query.filter_by(user=user, client=client).first_or_404() return render_delete_sqla(permassign, db, title=u"Confirm delete", message=u"Remove all permissions assigned to user {pname} for app ‘{title}’?".format( pname=user.pickername, title=client.title), success=u"You have revoked permisions for user {pname}".format(pname=user.pickername), next=url_for('.client_info', key=client.key)) else: team = Team.get(userid=kwargs['userid']) if not team: abort(404) permassign = TeamClientPermissions.query.filter_by(team=team, client=client).first_or_404() return render_delete_sqla(permassign, db, title=u"Confirm delete", message=u"Remove all permissions assigned to team ‘{pname}’ for app ‘{title}’?".format( pname=team.title, title=client.title), success=u"You have revoked permisions for team {title}".format(title=team.title), next=url_for('.client_info', key=client.key))
def permission_user_edit(client, kwargs): if client.user: user = User.get(userid=kwargs['userid']) if not user: abort(404) available_perms = Permission.query.filter(db.or_( Permission.allusers == True, Permission.user == g.user)).order_by('name').all() permassign = UserClientPermissions.query.filter_by(user=user, client=client).first_or_404() elif client.org: team = Team.get(userid=kwargs['userid']) if not team: abort(404) available_perms = Permission.query.filter(db.or_( Permission.allusers == True, Permission.org == client.org)).order_by('name').all() permassign = TeamClientPermissions.query.filter_by(team=team, client=client).first_or_404() form = PermissionEditForm() form.perms.choices = [(ap.name, u"{name} – {title}".format(name=ap.name, title=ap.title)) for ap in available_perms] if request.method == 'GET': if permassign: form.perms.data = permassign.access_permissions.split(u' ') if form.validate_on_submit(): form.perms.data.sort() perms = u' '.join(form.perms.data) if not perms: db.session.delete(permassign) else: permassign.access_permissions = perms db.session.commit() if perms: if client.user: flash(u"Permissions have been updated for user {pname}".format(pname=user.pickername), 'success') else: flash(u"Permissions have been updated for team {title}".format(title=team.title), 'success') else: if client.user: flash(u"All permissions have been revoked for user {pname}".format(pname=user.pickername), 'success') else: flash(u"All permissions have been revoked for team {title}".format(title=team.title), 'success') return render_redirect(url_for('.client_info', key=client.key), code=303) return render_form(form=form, title="Edit permissions", formid="perm_edit", submit="Save changes", ajax=True)
def profile_merge(): if "merge_userid" not in session: return redirect(get_next_url(), code=302) other_user = User.get(userid=session["merge_userid"]) if other_user is None: session.pop("merge_userid", None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if "merge" in request.form: new_user = merge_users(g.user, other_user) login_internal(new_user) user_data_changed.send(new_user, changes=["merge"]) flash(_("Your accounts have been merged"), "success") session.pop("merge_userid", None) db.session.commit() return redirect(get_next_url(), code=303) else: session.pop("merge_userid", None) return redirect(get_next_url(), code=303) return render_template("merge.html", form=form, user=g.user, other_user=other_user, login_registry=login_registry)
def permission_user_delete(auth_client, kwargs): if auth_client.user: user = User.get(buid=kwargs['buid']) if not user: abort(404) permassign = AuthClientUserPermissions.get(auth_client=auth_client, user=user) if not permassign: abort(404) return render_delete_sqla( permassign, db, title=_("Confirm delete"), message= _("Remove all permissions assigned to user {pname} for app ‘{title}’?" ).format(pname=user.pickername, title=auth_client.title), success=_("You have revoked permisions for user {pname}").format( pname=user.pickername), next=url_for('.client_info', key=auth_client.buid), ) else: team = Team.get(buid=kwargs['buid']) if not team: abort(404) permassign = AuthClientTeamPermissions.get(auth_client=auth_client, team=team) if not permassign: abort(404) return render_delete_sqla( permassign, db, title=_("Confirm delete"), message= _("Remove all permissions assigned to team ‘{pname}’ for app ‘{title}’?" ).format(pname=team.title, title=auth_client.title), success=_("You have revoked permisions for team {title}").format( title=team.title), next=url_for('.client_info', key=auth_client.buid), )
def account_merge(): if 'merge_buid' not in session: return redirect(get_next_url(), code=302) other_user = User.get(buid=session['merge_buid']) if other_user is None: session.pop('merge_buid', None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if 'merge' in request.form: new_user = merge_users(current_auth.user, other_user) login_internal(new_user) flash(_("Your accounts have been merged"), 'success') session.pop('merge_buid', None) db.session.commit() user_data_changed.send(new_user, changes=['merge']) return redirect(get_next_url(), code=303) else: session.pop('merge_buid', None) return redirect(get_next_url(), code=303) return render_template('merge.html.jinja2', form=form, user=current_auth.user, other_user=other_user, login_registry=login_registry)
def profile_merge(): if 'merge_userid' not in session: return redirect(get_next_url(), code=302) other_user = User.get(userid=session['merge_userid']) if other_user is None: session.pop('merge_userid', None) return redirect(get_next_url(), code=302) form = ProfileMergeForm() if form.validate_on_submit(): if 'merge' in request.form: new_user = merge_users(g.user, other_user) login_internal(new_user) user_data_changed.send(new_user, changes=['merge']) flash("Your accounts have been merged.", 'success') session.pop('merge_userid', None) return redirect(get_next_url(), code=303) else: session.pop('merge_userid', None) return redirect(get_next_url(), code=303) return render_template("merge.html", form=form, user=g.user, other_user=other_user, login_registry=login_registry)
def then_user_registered(context): user = User.get(username=context.test_user['username']) assert user is not None assert len(user.emailclaims) == 1
def oauth_token(): """ OAuth2 server -- token endpoint (confidential clients only) """ # Always required parameters grant_type = request.form.get('grant_type') client = g.client # Provided by @requires_client_login scope = request.form.get('scope', u'').split(u' ') # if grant_type == 'authorization_code' (POST) code = request.form.get('code') redirect_uri = request.form.get('redirect_uri') # if grant_type == 'password' (POST) username = request.form.get('username') password = request.form.get('password') # if grant_type == 'client_credentials' userid = request.form.get('userid') # Validations 1: Required parameters if not grant_type: return oauth_token_error('invalid_request', _("Missing grant_type")) # grant_type == 'refresh_token' is not supported. All tokens are permanent unless revoked if grant_type not in ['authorization_code', 'client_credentials', 'password']: return oauth_token_error('unsupported_grant_type') # Validations 2: client scope if grant_type == 'client_credentials': # Client data; user isn't part of it OR trusted client and automatic scope try: # FIXME: What is this verifyscope doing? That this scope is valid or that this client has access? verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) if userid: if client.trusted: user = User.get(userid=userid) if user: token = oauth_make_token(user=user, client=client, scope=client.scope) return oauth_token_success(token, userinfo=get_userinfo( user=token.user, client=client, scope=token.scope)) else: return oauth_token_error('invalid_grant', _("Unknown user")) else: return oauth_token_error('invalid_grant', _("Untrusted client")) else: token = oauth_make_token(user=None, client=client, scope=scope) return oauth_token_success(token) # Validations 3: auth code elif grant_type == 'authorization_code': authcode = AuthCode.query.filter_by(code=code, client=client).first() if not authcode: return oauth_token_error('invalid_grant', _("Unknown auth code")) if not authcode.is_valid(): db.session.delete(authcode) db.session.commit() return oauth_token_error('invalid_grant', _("Expired auth code")) # Validations 3.1: scope in authcode if not scope or scope[0] == '': return oauth_token_error('invalid_scope', _("Scope is blank")) if not set(scope).issubset(set(authcode.scope)): return oauth_token_error('invalid_scope', _("Scope expanded")) else: # Scope not provided. Use whatever the authcode allows scope = authcode.scope if redirect_uri != authcode.redirect_uri: return oauth_token_error('invalid_client', _("redirect_uri does not match")) token = oauth_make_token(user=authcode.user, client=client, scope=scope) db.session.delete(authcode) return oauth_token_success(token, userinfo=get_userinfo( user=authcode.user, client=client, scope=token.scope, session=authcode.session)) elif grant_type == 'password': # Validations 4.1: password grant_type is only for trusted clients if not client.trusted: # Refuse to untrusted clients return oauth_token_error('unauthorized_client', _("Client is not trusted for password grant_type")) # Validations 4.2: Are username and password provided and correct? if not username or not password: return oauth_token_error('invalid_request', _("Username or password not provided")) user = getuser(username) if not user: return oauth_token_error('invalid_client', _("No such user")) # XXX: invalid_client doesn't seem right if not user.password_is(password): return oauth_token_error('invalid_client', _("Password mismatch")) # Validations 4.3: verify scope try: verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) # All good. Grant access token = oauth_make_token(user=user, client=client, scope=scope) return oauth_token_success(token, userinfo=get_userinfo(user=user, client=client, scope=scope))
def then_user_registered(context): # just one user exists, the first one user = User.get(username=context.test_user['username']) assert user is not None
def oauth_token(): """ OAuth2 server -- token endpoint (confidential clients only) """ # Always required parameters grant_type = request.form.get('grant_type') client = g.client # Provided by @requires_client_login scope = request.form.get('scope', u'').split(u' ') # if grant_type == 'authorization_code' (POST) code = request.form.get('code') redirect_uri = request.form.get('redirect_uri') # if grant_type == 'password' (POST) username = request.form.get('username') password = request.form.get('password') # if grant_type == 'client_credentials' buid = request.form.get('buid') or request.form.get('userid') # XXX: Deprecated userid parameter # Validations 1: Required parameters if not grant_type: return oauth_token_error('invalid_request', _("Missing grant_type")) # grant_type == 'refresh_token' is not supported. All tokens are permanent unless revoked if grant_type not in ['authorization_code', 'client_credentials', 'password']: return oauth_token_error('unsupported_grant_type') # Validations 2: client scope if grant_type == 'client_credentials': # Client data; user isn't part of it OR trusted client and automatic scope try: # FIXME: What is this verifyscope doing? That this scope is valid or that this client has access? verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) if buid: if client.trusted: user = User.get(buid=buid) if user: token = oauth_make_token(user=user, client=client, scope=[]) return oauth_token_success( token, userinfo=get_userinfo( user=token.user, client=client, scope=token.effective_scope)) else: return oauth_token_error('invalid_grant', _("Unknown user")) else: return oauth_token_error('invalid_grant', _("Untrusted client")) else: token = oauth_make_token(user=None, client=client, scope=scope) return oauth_token_success(token) # Validations 3: auth code elif grant_type == 'authorization_code': authcode = AuthCode.query.filter_by(code=code, client=client).first() if not authcode: return oauth_token_error('invalid_grant', _("Unknown auth code")) if not authcode.is_valid(): db.session.delete(authcode) db.session.commit() return oauth_token_error('invalid_grant', _("Expired auth code")) # Validations 3.1: scope in authcode if not scope or scope[0] == '': return oauth_token_error('invalid_scope', _("Scope is blank")) if not set(scope).issubset(set(authcode.scope)): return oauth_token_error('invalid_scope', _("Scope expanded")) else: # Scope not provided. Use whatever the authcode allows scope = authcode.scope if redirect_uri != authcode.redirect_uri: return oauth_token_error('invalid_client', _("redirect_uri does not match")) token = oauth_make_token(user=authcode.user, client=client, scope=scope) db.session.delete(authcode) return oauth_token_success(token, userinfo=get_userinfo( user=authcode.user, client=client, scope=token.effective_scope, session=authcode.session)) elif grant_type == 'password': # Validations 4.1: password grant_type is only for trusted clients if not client.trusted: # Refuse to untrusted clients return oauth_token_error('unauthorized_client', _("Client is not trusted for password grant_type")) # Validations 4.2: Are username and password provided and correct? if not username or not password: return oauth_token_error('invalid_request', _("Username or password not provided")) user = getuser(username) if not user: return oauth_token_error('invalid_client', _("No such user")) # XXX: invalid_client doesn't seem right if not user.password_is(password): return oauth_token_error('invalid_client', _("Password mismatch")) # Validations 4.3: verify scope try: verifyscope(scope, client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', unicode(scopeex)) # All good. Grant access token = oauth_make_token(user=user, client=client, scope=scope) return oauth_token_success(token, userinfo=get_userinfo(user=user, client=client, scope=scope))
def oauth_token(): """ OAuth2 server -- token endpoint (confidential clients only) """ # Always required parameters grant_type = request.form.get('grant_type') auth_client = current_auth.auth_client # Provided by @requires_client_login scope = request.form.get('scope', '').split(' ') # if grant_type == 'authorization_code' (POST) code = request.form.get('code') redirect_uri = request.form.get('redirect_uri') # if grant_type == 'password' (POST) username = request.form.get('username') password = request.form.get('password') # if grant_type == 'client_credentials' buid = request.form.get('buid') or request.form.get( 'userid') # XXX: Deprecated userid parameter # Validations 1: Required parameters if not grant_type: return oauth_token_error('invalid_request', _("Missing grant_type")) # grant_type == 'refresh_token' is not supported. All tokens are permanent unless revoked if grant_type not in [ 'authorization_code', 'client_credentials', 'password' ]: return oauth_token_error('unsupported_grant_type') # Validations 2: client scope if grant_type == 'client_credentials': # AuthClient data; user isn't part of it OR trusted client and automatic scope try: # Confirm the client has access to the scope it wants verifyscope(scope, auth_client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', str(scopeex)) if buid: if auth_client.trusted: user = User.get(buid=buid) if user: # This client is trusted and can receive a user access token. # However, don't grant it the scope it wants as the user's # permission was not obtained. Instead, the client's # pre-approved scope will be used for the token's effective scope. token = oauth_make_token(user=user, auth_client=auth_client, scope=[]) return oauth_token_success( token, userinfo=get_userinfo( user=token.user, auth_client=auth_client, scope=token.effective_scope, ), ) else: return oauth_token_error('invalid_grant', _("Unknown user")) else: return oauth_token_error('invalid_grant', _("Untrusted client app")) else: token = oauth_make_token(user=None, auth_client=auth_client, scope=scope) return oauth_token_success(token) # Validations 3: auth code elif grant_type == 'authorization_code': authcode = AuthCode.get_for_client(auth_client=auth_client, code=code) if not authcode: return oauth_token_error('invalid_grant', _("Unknown auth code")) if not authcode.is_valid(): db.session.delete(authcode) db.session.commit() return oauth_token_error('invalid_grant', _("Expired auth code")) # Validations 3.1: scope in authcode if not scope or scope[0] == '': return oauth_token_error('invalid_scope', _("Scope is blank")) if not set(scope).issubset(set(authcode.scope)): return oauth_token_error('invalid_scope', _("Scope expanded")) else: # Scope not provided. Use whatever the authcode allows scope = authcode.scope if redirect_uri != authcode.redirect_uri: return oauth_token_error('invalid_client', _("redirect_uri does not match")) token = oauth_make_token(user=authcode.user, auth_client=auth_client, scope=scope) db.session.delete(authcode) return oauth_token_success( token, userinfo=get_userinfo( user=authcode.user, auth_client=auth_client, scope=token.effective_scope, user_session=authcode.user_session, ), ) elif grant_type == 'password': # Validations 4.1: password grant_type is only for trusted clients if not auth_client.trusted: # Refuse to untrusted clients return oauth_token_error( 'unauthorized_client', _("AuthClient is not trusted for password grant_type"), ) # Validations 4.2: Are username and password provided and correct? if not username or not password: return oauth_token_error('invalid_request', _("Username or password not provided")) user = getuser(username) if not user: return oauth_token_error( 'invalid_client', _("No such user")) # XXX: invalid_client doesn't seem right if not user.password_is(password): return oauth_token_error('invalid_client', _("Password mismatch")) # Validations 4.3: verify scope try: verifyscope(scope, auth_client) except ScopeException as scopeex: return oauth_token_error('invalid_scope', str(scopeex)) # All good. Grant access token = oauth_make_token(user=user, auth_client=auth_client, scope=scope) return oauth_token_success( token, userinfo=get_userinfo(user=user, auth_client=auth_client, scope=scope), )
def then_user_registered(context): user = User.get(username=context.test_user['username']) assert user is not None assert len(user.emailclaims) is 1
def permission_user_edit(auth_client, kwargs): if auth_client.user: user = User.get(buid=kwargs['buid']) if not user: abort(404) permassign = AuthClientUserPermissions.get(auth_client=auth_client, user=user) if not permassign: abort(404) elif auth_client.organization: team = Team.get(buid=kwargs['buid']) if not team: abort(404) permassign = AuthClientTeamPermissions.get(auth_client=auth_client, team=team) if not permassign: abort(404) form = PermissionEditForm() if request.method == 'GET': if permassign: form.perms.data = permassign.access_permissions if form.validate_on_submit(): perms = ' '.join(sorted(form.perms.data.split())) if not perms: db.session.delete(permassign) else: permassign.access_permissions = perms db.session.commit() if perms: if auth_client.user: flash( _("Permissions have been updated for user {pname}").format( pname=user.pickername), 'success', ) else: flash( _("Permissions have been updated for team {title}").format( title=team.title), 'success', ) else: if auth_client.user: flash( _("All permissions have been revoked for user {pname}"). format(pname=user.pickername), 'success', ) else: flash( _("All permissions have been revoked for team {title}"). format(title=team.title), 'success', ) return render_redirect(url_for('.client_info', key=auth_client.buid), code=303) return render_form( form=form, title=_("Edit permissions"), formid='perm_edit', submit=_("Save changes"), ajax=True, )