Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"error":"invalid_jwt_token","error_description":"iat missing" #153

Closed
alextoro85 opened this issue Jan 4, 2023 · 6 comments · Fixed by #189
Closed

"error":"invalid_jwt_token","error_description":"iat missing" #153

alextoro85 opened this issue Jan 4, 2023 · 6 comments · Fixed by #189

Comments

@alextoro85
Copy link

After a succed login and launch validation, when I want to getContextMembershipForPayload (Lti1p3Nrps), it fails by responding "iat missing".
I tried using OAT\Library\Lti1p3Core\Service\Client\LtiServiceClient directly. Same happens.

Whole error:
Cannot get context membership for payload: Cannot get context membership for claim: Cannot get context membership: Cannot get access token: Client error: POST https://developer.anthology.com/api/v1/gateway/oauth2/jwttoken resulted in a 400 Bad Request response: {"error":"invalid_jwt_token","error_description":"iat missing"}

So it fails in getAccessToken from LtiServiceClient

The thing is that if I print the token claims... iat appears. So... very very strange.

Any ideas?

Thanks in advance

@richard015ar
Copy link

Same problem. I can see this is a Blackboard issue, isn't it? how did you solve it @alextoro85?

@alextoro85
Copy link
Author

alextoro85 commented Jun 5, 2024

Hi @richard015ar,
If I'm not wrong... I think the issue here was Blackboard is not accepting microseconds.
So, you can overwrite /src/Security/Jwt/Builder/Builder.php and just after $now = Carbon::now(); add:
$now->setMicrosecond(0);

@richard015ar
Copy link

That did the trick, thank you @alextoro85! you saved me several hours debugging it.
It's a little bit disappointing knowing that I'll have to fork or manually change it to make it work, only for Blackboard, tbh.

@alextoro85
Copy link
Author

alextoro85 commented Jun 5, 2024

/I know @richard015ar, very disappointing,
as a tip, if you are using composer you can do something like I did:

"autoload": {
        "psr-4": {
            "App\\": "src/"
        },
        "exclude-from-classmap": [
            "vendor/oat-sa/lib-lti1p3-core/src/Security/Jwt/Builder/Builder.php"
        ],
        "files": [
            "app/override/lib-lti1p3-core/src/Security/Jwt/Builder/Builder.php"
        ]
}

@richard015ar
Copy link

Nice approach! I will definitely try it now!

@d34dman
Copy link

d34dman commented Sep 6, 2024

Checking the Specification for JWT https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6.

[4.1.6](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6).  "iat" (Issued At) Claim

   The "iat" (issued at) claim identifies the time at which the JWT was
   issued.  This claim can be used to determine the age of the JWT.  Its
   value MUST be a number containing a NumericDate value.  Use of this
   claim is OPTIONAL.

According to JWT specification, IAT claim "MUST" be a NumericDate Value.

And NumericDate is defined in the document as follows,

NumericDate
      A JSON numeric value representing the number of seconds from
      1970-01-01T00:00:00Z UTC until the specified UTC date/time,
      ignoring leap seconds.  This is equivalent to the IEEE Std 1003.1,
      2013 Edition [[POSIX.1](https://datatracker.ietf.org/doc/html/rfc7519#ref-POSIX.1)] definition "Seconds Since the Epoch", in
      which each day is accounted for by exactly 86400 seconds, other
      than that non-integer values can be represented.  See [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339)
      [[RFC3339](https://datatracker.ietf.org/doc/html/rfc3339)] for details regarding date/times in general and UTC in
      particular.

Since time format for toDateTimeImmutable is hardcoded in Carbon to 'Y-m-d H:i:s.u', we get a non integer value for IAT.

    /**
     * Return native toDateTimeImmutable PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toDateTimeImmutable());
     * ```
     *
     * @return DateTimeImmutable
     */
    public function toDateTimeImmutable()
    {
        return new DateTimeImmutable($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone());
    }

MR in #189 does resolve the problem due to a side effect that format format method seems to ignore the .u part when microseconds is set to 0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants