Example #1
0
    def create_refresh_token(self):
        """
        Create a new refresh token and add its entry to the database.

        Return:
            JWTResult: the refresh token result
        """
        driver = SQLAlchemyDriver(self.db)
        with driver.session as current_session:
            user = query_for_user(session=current_session, username=self.username)

            if not user:
                raise EnvironmentError(
                    "no user found with given username: "******"jti"],
                    userid=user.id,
                    expires=jwt_result.claims["exp"],
                )
            )

            return jwt_result
Example #2
0
    def __call__(self,
                 client,
                 grant_type,
                 expires_in=None,
                 scope=None,
                 include_refresh_token=True,
                 nonce=None,
                 refresh_token=None,
                 refresh_token_claims=None):
        """
        Generate the token response, which looks like the following:

            {
                'token_type': 'Bearer',
                'id_token': 'eyJhb[...long encoded JWT...]OnoVQ',
                'access_token': 'eyJhb[...long encoded JWT...]evfxA',
                'refresh_token': 'eyJhb[ ... long encoded JWT ... ]KnLJA',
                'expires_in': 1200,
            }

        This function will be called in authlib internals.

        Args:
            client: not used (would be used to determine expiration)
            grant_type: not used
            expires_in: not used (see expiration times configured above)
            scope (List[str]): list of requested scopes
            include_refresh_token: not used
            nonce (str): "nonsense" to include in ID token (see OIDC spec)
            refresh_token:
                for a refresh token grant, pass in the previous refresh token
                to return that same token again instead of generating a new one
                (otherwise this will let the refresh token refresh itself)
            refresh_token_claims (dict):
                also for a refresh token grant, pass the previous refresh token
                claims (to avoid having to encode or decode the refresh token
                here)
        """
        # Find the ``User`` model.
        # The way to do this depends on the grant type.
        if grant_type == 'authorization_code':
            # For authorization code grant, get the code from either the query
            # string or the form data, and use that to look up the user.
            if flask.request.method == 'GET':
                code = flask.request.args.get('code')
            else:
                code = flask.request.form.get('code')
            user = (current_session.query(AuthorizationCode).filter_by(
                code=code).first().user)
        if grant_type == 'refresh_token':
            # For refresh token, the user ID is the ``sub`` field in the token.
            user = (current_session.query(User).filter_by(
                id=int(refresh_token_claims['sub'])).first())

        keypair = flask.current_app.keypairs[0]
        id_token = generate_signed_id_token(
            kid=keypair.kid,
            private_key=keypair.private_key,
            user=user,
            expires_in=self.ACCESS_TOKEN_EXPIRES_IN,
            client_id=client.client_id,
            audiences=scope,
            nonce=nonce,
        )
        access_token = generate_signed_access_token(
            kid=keypair.kid,
            private_key=keypair.private_key,
            user=user,
            expires_in=self.ACCESS_TOKEN_EXPIRES_IN,
            scopes=scope,
        )
        # If ``refresh_token`` was passed (for instance from the refresh
        # grant), use that instead of generating a new one.
        if refresh_token is None:
            refresh_token, _ = generate_signed_refresh_token(
                kid=keypair.kid,
                private_key=keypair.private_key,
                user=user,
                expires_in=self.REFRESH_TOKEN_EXPIRES_IN,
                scopes=scope,
            )
        # ``expires_in`` is just the access token expiration time.
        expires_in = self.ACCESS_TOKEN_EXPIRES_IN
        return {
            'token_type': 'Bearer',
            'id_token': id_token,
            'access_token': access_token,
            'refresh_token': refresh_token,
            'expires_in': expires_in,
        }
Example #3
0
def generate_token_response(client,
                            grant_type,
                            expires_in=None,
                            user=None,
                            scope=None,
                            include_refresh_token=True,
                            nonce=None,
                            refresh_token=None,
                            refresh_token_claims=None,
                            **kwargs):
    # prevent those bothersome "not bound to session" errors
    if user not in current_session:
        user = current_session.query(User).filter_by(id=user.id).first()

    if not user:
        # Find the ``User`` model.
        # The way to do this depends on the grant type.
        if grant_type == "authorization_code":
            # For authorization code grant, get the code from either the query
            # string or the form data, and use that to look up the user.
            if flask.request.method == "GET":
                code = flask.request.args.get("code")
            else:
                code = flask.request.form.get("code")
            user = (current_session.query(AuthorizationCode).filter_by(
                code=code).first().user)
        if grant_type == "refresh_token":
            # For refresh token, the user ID is the ``sub`` field in the token.
            user = (current_session.query(User).filter_by(
                id=int(refresh_token_claims["sub"])).first())

    keypair = flask.current_app.keypairs[0]

    linked_google_email = get_linked_google_account_email(user.id)
    linked_google_account_exp = get_linked_google_account_exp(user.id)

    if not isinstance(scope, list):
        scope = scope.split(" ")

    access_token = generate_signed_access_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=user,
        expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
        scopes=scope,
        client_id=client.client_id,
        linked_google_email=linked_google_email,
    ).token
    id_token = generate_signed_id_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=user,
        expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
        client_id=client.client_id,
        audiences=scope,
        nonce=nonce,
        linked_google_email=linked_google_email,
        linked_google_account_exp=linked_google_account_exp,
        auth_flow_type=AuthFlowTypes.CODE,
        access_token=access_token,
    ).token
    # If ``refresh_token`` was passed (for instance from the refresh
    # grant), use that instead of generating a new one.
    if refresh_token is None:
        refresh_token = generate_signed_refresh_token(
            kid=keypair.kid,
            private_key=keypair.private_key,
            user=user,
            expires_in=config["REFRESH_TOKEN_EXPIRES_IN"],
            scopes=scope,
            client_id=client.client_id,
        ).token
    # ``expires_in`` is just the access token expiration time.
    expires_in = config["ACCESS_TOKEN_EXPIRES_IN"]
    return {
        "token_type": "Bearer",
        "id_token": id_token,
        "access_token": access_token,
        "refresh_token": refresh_token,
        "expires_in": expires_in,
    }