Id_token valid but returns "Unable to parse authentication token."

Hi everyone,

I am trying to validate the id token in my flask application using the code snippet here Auth0 Python API SDK Quickstarts: Authorization. The code below works for my localhost environment server but when I deployed it to Nginx, it somehow broke. However, access token validates perfectly fine.

Here’s my sample API call:
https://sampledomain/test

Flask:

@app.route("/test")
@cross_origin(origin='localhost', headers=['Content-Type','IdToken'])
@requires_id_token
def test():
   return "working"
def get_id_token_auth_header():
    """Obtains the idToken from the idtoken Header
    """
    auth = request.headers.get("IdToken", None)
    if not auth:
        raise AuthError({"code": "id_token_header_missing",
                        "description":
                            "id_token header is expected"}, 401)
    parts = auth.split()
    if parts[0].lower() != "bearer":
        raise AuthError({"code": "invalid_header",
                        "description":
                            "id_token header must start with"
                            " Bearer"}, 401)
    elif len(parts) == 1:
        raise AuthError({"code": "invalid_header",
                        "description": "id_token not found"}, 401)
    elif len(parts) > 2:
        raise AuthError({"code": "invalid_header",
                        "description":
                            "id_token header must be"
                            " Bearer token"}, 401)
    id_token = parts[1]
    return id_token

In this algorithm, everything is the same except for the ‘audience’ which is the Client Id of my auth0

def requires_id_token(f):
    """Determines if the id Token is valid
    """
    @wraps(f)
    def decorated(*args, **kwargs):
        token = get_id_token_auth_header()
        jsonurl = urlopen("https://"+AUTH0_DOMAIN+"/.well-known/jwks.json")
        jwks = json.loads(jsonurl.read())
        unverified_header = jwt.get_unverified_header(token)
        rsa_key = {}
        for key in jwks["keys"]:
            if key["kid"] == unverified_header["kid"]:
                rsa_key = {
                    "kty": key["kty"],
                    "kid": key["kid"],
                    "use": key["use"],
                    "n": key["n"],
                    "e": key["e"]
                }
        if rsa_key:
            try:
                payload = jwt.decode(
                    token,
                    rsa_key,
                    algorithms=ALGORITHMS,
                    audience=< CLIENT ID HERE >,
                    issuer="https://"+AUTH0_DOMAIN+"/"
                )
            except jwt.ExpiredSignatureError:
                raise AuthError({"code": "token_expired",
                                "description": "token is expired"}, 401)
            except jwt.JWTClaimsError:
                raise AuthError({"code": "invalid_claims",
                                "description":
                                    "incorrect claims,"
                                    "please check the audience and issuer"}, 401)
            except Exception:
                raise AuthError({"code": "invalid_header",
                                "description":
                                    "Unable to parse authentication"
                                    " token."}, 401)

            _request_ctx_stack.top.current_user = payload
            return f(*args, **kwargs)
        raise AuthError({"code": "invalid_header",
                        "description": "Unable to find appropriate key"}, 401)
    return decorated

However, when I tried either my own application or postman, I receive error 401,

{
    "code": "invalid_header",
    "description": "Unable to parse authentication token."
}

I verified the id_token on jwt.io and it is valid.

May I know what might be the issue?

PS: Didn’t include authorization because it is working.

Hi @shanegohwenhan

For an API call you should be using an Access Token, not an ID token.
Your get_id_token_auth_header function has the comment “Obtains the Access token”.

I haven’t looked to closely at your code, but wouldn’t be surprised if you are looking for an access token field in the ID token.

Rewrite it so that it is using an access token, and make sure you are passing an access token.

John

Hi John, thanks for the reply.

I had added additional rules to the access token which includes the email in it. It solved my issue and I did not need the id token anymore.
Also, I found out that the issue is not with the claims themselves, however, it’s with the .env file that wasn’t specified properly in my .ini file in wsgi, causing an issue when I tried to set the email attribute to my flask session variable. It’s all working fine now!