Esempio n. 1
0
def oauth_make_auth_code(client, scope, redirect_uri):
    """
    Make an auth code for a given client. Caller must commit
    the database session for this to work.
    """
    authcode = AuthCode(user=g.user, session=g.usersession, client=client, scope=scope, redirect_uri=redirect_uri)
    authcode.code = newsecret()
    db.session.add(authcode)
    return authcode.code
Esempio n. 2
0
def oauth_make_auth_code(client, scope, redirect_uri):
    """
    Make an auth code for a given client. Caller must commit
    the database session for this to work.
    """
    authcode = AuthCode(user=g.user, client=client, scope=scope, redirect_uri=redirect_uri)
    authcode.code = newsecret()
    db.session.add(authcode)
    return authcode.code
Esempio n. 3
0
def oauth_make_auth_code(auth_client, scope, redirect_uri):
    """
    Make an auth code for a given client. Caller must commit
    the database session for this to work.
    """
    authcode = AuthCode(
        user=current_auth.user,
        user_session=current_auth.session,
        auth_client=auth_client,
        scope=scope,
        redirect_uri=redirect_uri[:1024],
    )
    authcode.code = newsecret()
    db.session.add(authcode)
    return authcode.code
Esempio n. 4
0
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),
        )