{"action":"opened","number":113,"pull_request":{"url":"https://api.github.com/repos/jwt/ruby-jwt/pulls/113","id":49249579,"html_url":"https://github.com/jwt/ruby-jwt/pull/113","diff_url":"https://github.com/jwt/ruby-jwt/pull/113.diff","patch_url":"https://github.com/jwt/ruby-jwt/pull/113.patch","issue_url":"https://api.github.com/repos/jwt/ruby-jwt/issues/113","number":113,"state":"open","locked":false,"title":"Relax restrictions on \"jti\" claim verification","user":{"login":"lwe","id":83660,"avatar_url":"https://avatars.githubusercontent.com/u/83660?v=3","gravatar_id":"","url":"https://api.github.com/users/lwe","html_url":"https://github.com/lwe","followers_url":"https://api.github.com/users/lwe/followers","following_url":"https://api.github.com/users/lwe/following{/other_user}","gists_url":"https://api.github.com/users/lwe/gists{/gist_id}","starred_url":"https://api.github.com/users/lwe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lwe/subscriptions","organizations_url":"https://api.github.com/users/lwe/orgs","repos_url":"https://api.github.com/users/lwe/repos","events_url":"https://api.github.com/users/lwe/events{/privacy}","received_events_url":"https://api.github.com/users/lwe/received_events","type":"User","site_admin":false},"body":"The RFC has the following to say about the \"jti\" claim:\r\n\r\n> The \"jti\" (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well.  The \"jti\" claim can be used to prevent the JWT from being replayed.  The \"jti\" value is a case- sensitive string.  Use of this claim is OPTIONAL.\r\n> https://tools.ietf.org/html/rfc7519#section-4.1.7\r\n\r\nThe current implementation expects that the `jti` is built as:\r\n\r\n```\r\nMD5( secret + \":\" + iat )\r\n```\r\n\r\nanything else is not considered a valid `jti`. There are several issues with the current implementation:\r\n\r\n1. `secret + \":\" + iat` is not exactly collision safe :) using random UUIDs is safer I'd say.\r\n2. It was only verified when it was present in the payload, so it was skipped when it was missing from the payload\r\n3. In the RFC there are no rules defined on how the \"jti\" claim should be validated\r\n\r\nThis pull request simply relaxes the verification of the \"jti\" claim to be present. This is in line with other implementations like the one for Java or Python. (FYI, there are other implementations that perform additional checks, the one seen most common is to verify against a fixed value supplied in the `verify` call).\r\n\r\nIt is my opinion that the library should just provide basic validation and make no additional assumption about the `jti`. Any additional verification / validation (e.g. replay checks, value checks) must be checked by the application and should be out of the scope for the library.\r\n\r\nPS: Yes, one could argue about having the option to supply an expected value for the \"jti\" claim, but this is IMO not really reasonable, because it (should) change for every JWT generated. So it's not something quasi-static like e.g. the issuer or audience.","created_at":"2015-10-30T09:53:30Z","updated_at":"2015-10-30T09:53:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/jwt/ruby-jwt/pulls/113/commits","review_comments_url":"https://api.github.com/repos/jwt/ruby-jwt/pulls/113/comments","review_comment_url":"https://api.github.com/repos/jwt/ruby-jwt/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jwt/ruby-jwt/issues/113/comments","statuses_url":"https://api.github.com/repos/jwt/ruby-jwt/statuses/320306bbd64f0c30bc720c8bb0cd267c4b020dce","head":{"label":"lwe:lwe-jti-validation-fix","ref":"lwe-jti-validation-fix","sha":"320306bbd64f0c30bc720c8bb0cd267c4b020dce","user":{"login":"lwe","id":83660,"avatar_url":"https://avatars.githubusercontent.com/u/83660?v=3","gravatar_id":"","url":"https://api.github.com/users/lwe","html_url":"https://github.com/lwe","followers_url":"https://api.github.com/users/lwe/followers","following_url":"https://api.github.com/users/lwe/following{/other_user}","gists_url":"https://api.github.com/users/lwe/gists{/gist_id}","starred_url":"https://api.github.com/users/lwe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lwe/subscriptions","organizations_url":"https://api.github.com/users/lwe/orgs","repos_url":"https://api.github.com/users/lwe/repos","events_url":"https://api.github.com/users/lwe/events{/privacy}","received_events_url":"https://api.github.com/users/lwe/received_events","type":"User","site_admin":false},"repo":{"id":36711882,"name":"ruby-jwt","full_name":"lwe/ruby-jwt","owner":{"login":"lwe","id":83660,"avatar_url":"https://avatars.githubusercontent.com/u/83660?v=3","gravatar_id":"","url":"https://api.github.com/users/lwe","html_url":"https://github.com/lwe","followers_url":"https://api.github.com/users/lwe/followers","following_url":"https://api.github.com/users/lwe/following{/other_user}","gists_url":"https://api.github.com/users/lwe/gists{/gist_id}","starred_url":"https://api.github.com/users/lwe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lwe/subscriptions","organizations_url":"https://api.github.com/users/lwe/orgs","repos_url":"https://api.github.com/users/lwe/repos","events_url":"https://api.github.com/users/lwe/events{/privacy}","received_events_url":"https://api.github.com/users/lwe/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lwe/ruby-jwt","description":"JSON Web Token implementation in Ruby","fork":true,"url":"https://api.github.com/repos/lwe/ruby-jwt","forks_url":"https://api.github.com/repos/lwe/ruby-jwt/forks","keys_url":"https://api.github.com/repos/lwe/ruby-jwt/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lwe/ruby-jwt/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lwe/ruby-jwt/teams","hooks_url":"https://api.github.com/repos/lwe/ruby-jwt/hooks","issue_events_url":"https://api.github.com/repos/lwe/ruby-jwt/issues/events{/number}","events_url":"https://api.github.com/repos/lwe/ruby-jwt/events","assignees_url":"https://api.github.com/repos/lwe/ruby-jwt/assignees{/user}","branches_url":"https://api.github.com/repos/lwe/ruby-jwt/branches{/branch}","tags_url":"https://api.github.com/repos/lwe/ruby-jwt/tags","blobs_url":"https://api.github.com/repos/lwe/ruby-jwt/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lwe/ruby-jwt/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lwe/ruby-jwt/git/refs{/sha}","trees_url":"https://api.github.com/repos/lwe/ruby-jwt/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lwe/ruby-jwt/statuses/{sha}","languages_url":"https://api.github.com/repos/lwe/ruby-jwt/languages","stargazers_url":"https://api.github.com/repos/lwe/ruby-jwt/stargazers","contributors_url":"https://api.github.com/repos/lwe/ruby-jwt/contributors","subscribers_url":"https://api.github.com/repos/lwe/ruby-jwt/subscribers","subscription_url":"https://api.github.com/repos/lwe/ruby-jwt/subscription","commits_url":"https://api.github.com/repos/lwe/ruby-jwt/commits{/sha}","git_commits_url":"https://api.github.com/repos/lwe/ruby-jwt/git/commits{/sha}","comments_url":"https://api.github.com/repos/lwe/ruby-jwt/comments{/number}","issue_comment_url":"https://api.github.com/repos/lwe/ruby-jwt/issues/comments{/number}","contents_url":"https://api.github.com/repos/lwe/ruby-jwt/contents/{+path}","compare_url":"https://api.github.com/repos/lwe/ruby-jwt/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lwe/ruby-jwt/merges","archive_url":"https://api.github.com/repos/lwe/ruby-jwt/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lwe/ruby-jwt/downloads","issues_url":"https://api.github.com/repos/lwe/ruby-jwt/issues{/number}","pulls_url":"https://api.github.com/repos/lwe/ruby-jwt/pulls{/number}","milestones_url":"https://api.github.com/repos/lwe/ruby-jwt/milestones{/number}","notifications_url":"https://api.github.com/repos/lwe/ruby-jwt/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lwe/ruby-jwt/labels{/name}","releases_url":"https://api.github.com/repos/lwe/ruby-jwt/releases{/id}","created_at":"2015-06-02T06:07:45Z","updated_at":"2015-06-02T06:07:46Z","pushed_at":"2015-10-30T09:49:12Z","git_url":"git://github.com/lwe/ruby-jwt.git","ssh_url":"git@github.com:lwe/ruby-jwt.git","clone_url":"https://github.com/lwe/ruby-jwt.git","svn_url":"https://github.com/lwe/ruby-jwt","homepage":"","size":241,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"jwt:master","ref":"master","sha":"27c7412b3af8ccb7f62738816ecf0f0029a16e34","user":{"login":"jwt","id":10998651,"avatar_url":"https://avatars.githubusercontent.com/u/10998651?v=3","gravatar_id":"","url":"https://api.github.com/users/jwt","html_url":"https://github.com/jwt","followers_url":"https://api.github.com/users/jwt/followers","following_url":"https://api.github.com/users/jwt/following{/other_user}","gists_url":"https://api.github.com/users/jwt/gists{/gist_id}","starred_url":"https://api.github.com/users/jwt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jwt/subscriptions","organizations_url":"https://api.github.com/users/jwt/orgs","repos_url":"https://api.github.com/users/jwt/repos","events_url":"https://api.github.com/users/jwt/events{/privacy}","received_events_url":"https://api.github.com/users/jwt/received_events","type":"Organization","site_admin":false},"repo":{"id":1404127,"name":"ruby-jwt","full_name":"jwt/ruby-jwt","owner":{"login":"jwt","id":10998651,"avatar_url":"https://avatars.githubusercontent.com/u/10998651?v=3","gravatar_id":"","url":"https://api.github.com/users/jwt","html_url":"https://github.com/jwt","followers_url":"https://api.github.com/users/jwt/followers","following_url":"https://api.github.com/users/jwt/following{/other_user}","gists_url":"https://api.github.com/users/jwt/gists{/gist_id}","starred_url":"https://api.github.com/users/jwt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jwt/subscriptions","organizations_url":"https://api.github.com/users/jwt/orgs","repos_url":"https://api.github.com/users/jwt/repos","events_url":"https://api.github.com/users/jwt/events{/privacy}","received_events_url":"https://api.github.com/users/jwt/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/jwt/ruby-jwt","description":"JSON Web Token implementation in Ruby","fork":false,"url":"https://api.github.com/repos/jwt/ruby-jwt","forks_url":"https://api.github.com/repos/jwt/ruby-jwt/forks","keys_url":"https://api.github.com/repos/jwt/ruby-jwt/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jwt/ruby-jwt/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jwt/ruby-jwt/teams","hooks_url":"https://api.github.com/repos/jwt/ruby-jwt/hooks","issue_events_url":"https://api.github.com/repos/jwt/ruby-jwt/issues/events{/number}","events_url":"https://api.github.com/repos/jwt/ruby-jwt/events","assignees_url":"https://api.github.com/repos/jwt/ruby-jwt/assignees{/user}","branches_url":"https://api.github.com/repos/jwt/ruby-jwt/branches{/branch}","tags_url":"https://api.github.com/repos/jwt/ruby-jwt/tags","blobs_url":"https://api.github.com/repos/jwt/ruby-jwt/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jwt/ruby-jwt/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jwt/ruby-jwt/git/refs{/sha}","trees_url":"https://api.github.com/repos/jwt/ruby-jwt/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jwt/ruby-jwt/statuses/{sha}","languages_url":"https://api.github.com/repos/jwt/ruby-jwt/languages","stargazers_url":"https://api.github.com/repos/jwt/ruby-jwt/stargazers","contributors_url":"https://api.github.com/repos/jwt/ruby-jwt/contributors","subscribers_url":"https://api.github.com/repos/jwt/ruby-jwt/subscribers","subscription_url":"https://api.github.com/repos/jwt/ruby-jwt/subscription","commits_url":"https://api.github.com/repos/jwt/ruby-jwt/commits{/sha}","git_commits_url":"https://api.github.com/repos/jwt/ruby-jwt/git/commits{/sha}","comments_url":"https://api.github.com/repos/jwt/ruby-jwt/comments{/number}","issue_comment_url":"https://api.github.com/repos/jwt/ruby-jwt/issues/comments{/number}","contents_url":"https://api.github.com/repos/jwt/ruby-jwt/contents/{+path}","compare_url":"https://api.github.com/repos/jwt/ruby-jwt/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jwt/ruby-jwt/merges","archive_url":"https://api.github.com/repos/jwt/ruby-jwt/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jwt/ruby-jwt/downloads","issues_url":"https://api.github.com/repos/jwt/ruby-jwt/issues{/number}","pulls_url":"https://api.github.com/repos/jwt/ruby-jwt/pulls{/number}","milestones_url":"https://api.github.com/repos/jwt/ruby-jwt/milestones{/number}","notifications_url":"https://api.github.com/repos/jwt/ruby-jwt/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jwt/ruby-jwt/labels{/name}","releases_url":"https://api.github.com/repos/jwt/ruby-jwt/releases{/id}","created_at":"2011-02-23T21:45:17Z","updated_at":"2015-10-29T12:48:13Z","pushed_at":"2015-10-30T09:53:30Z","git_url":"git://github.com/jwt/ruby-jwt.git","ssh_url":"git@github.com:jwt/ruby-jwt.git","clone_url":"https://github.com/jwt/ruby-jwt.git","svn_url":"https://github.com/jwt/ruby-jwt","homepage":"","size":817,"stargazers_count":786,"watchers_count":786,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":85,"mirror_url":null,"open_issues_count":6,"forks":85,"open_issues":6,"watchers":786,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jwt/ruby-jwt/pulls/113"},"html":{"href":"https://github.com/jwt/ruby-jwt/pull/113"},"issue":{"href":"https://api.github.com/repos/jwt/ruby-jwt/issues/113"},"comments":{"href":"https://api.github.com/repos/jwt/ruby-jwt/issues/113/comments"},"review_comments":{"href":"https://api.github.com/repos/jwt/ruby-jwt/pulls/113/comments"},"review_comment":{"href":"https://api.github.com/repos/jwt/ruby-jwt/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jwt/ruby-jwt/pulls/113/commits"},"statuses":{"href":"https://api.github.com/repos/jwt/ruby-jwt/statuses/320306bbd64f0c30bc720c8bb0cd267c4b020dce"}},"merged":false,"mergeable":null,"mergeable_state":"unknown","merged_by":null,"comments":0,"review_comments":0,"commits":1,"additions":7,"deletions":15,"changed_files":2}}