[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.yml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n\n/tests export-ignore\n/docs export-ignore\n/.codecov.yml export-ignore\n/.editorconfig export-ignore\n/.gitattributes export-ignore\n/.gitignore export-ignore\n/.styleci.yml export-ignore\n/.travis.yml export-ignore\n/.github export-ignore\n/phpunit.xml.dist export-ignore\n/README.md export-ignore\n/mkdocs.yml export-ignore\n"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\nadvances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at tymon148@gmail.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributors Guide\n\nPlease read and understand the contribution guide before creating an issue or pull request.\n\n## Etiquette\n\nThis project is open source, and as such, the maintainers give their free time to build and maintain the source code held within. They make the code freely available in the hope that it will be of use to other developers. It would be extremely unfair for them to suffer abuse or anger for their hard work.\n\nPlease be considerate towards maintainers when raising issues or presenting pull requests. Let's show the world that developers are civilized and selfless people.\n\nIt's the duty of the maintainer to ensure that all submissions to the project are of sufficient quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.\n\n## Viability\n\nWhen requesting or submitting new features, first consider whether it might be useful to others. Open source projects are used by many developers, who may have entirely different needs to your own. Think about whether or not your feature is likely to be used by other users of the project.\n\n## Procedure\n\nBefore filing an issue:\n\n- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.\n- Check to make sure your feature suggestion isn't already present within the project.\n- Check the pull requests tab to ensure that the bug doesn't have a fix in progress.\n- Check the pull requests tab to ensure that the feature isn't already in progress.\n\nBefore submitting a pull request:\n\n- Ensure that your submission is [viable](#viability) for the project.\n- Check the codebase to ensure that your feature doesn't already exist.\n- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.\n\n## Requirements\n\nIf the project maintainer has any additional requirements, you will find them listed here.\n\n- No additional requirements.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "### Subject of the issue\nDescribe your issue here.\n\n### Your environment\n| Q                 | A\n| ----------------- | ---\n| Bug?              | no / yes\n| New Feature?      | no / yes\n| Framework         | Laravel / Lumen\n| Framework version | 5.x.y\n| Package version   | 1.x.y\n| PHP version       | 5.x.y / 7.x.y\n\n### Steps to reproduce\nTell us how to reproduce this issue.\n\n### Expected behaviour\nTell us what should happen\n\n### Actual behaviour\nTell us what happens instead\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "daysUntilStale: 60\ndaysUntilClose: 7\nexemptLabels:\n  - pinned\n  - security\nstaleLabel: stale\n"
  },
  {
    "path": ".github/workflows/phpunit.yml",
    "content": "name: PHPUnit tests\n\non:\n  push:\n  release:\n    types:\n      - published\n\njobs:\n  php-tests:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        php: [8.0, 8.1, 8.2, 8.3, 8.4, 8.5]\n        laravel: [9.*, 10.*, 11.*, 12.*, 13.*]\n        os: [ubuntu-latest]\n        coverage: [none]\n        stability: [prefer-lowest, prefer-stable]\n        include:\n          - php: 8.5\n            laravel: 12.*\n            os: ubuntu-latest\n            coverage: xdebug\n            stability: prefer-stable\n        exclude:\n          - php: 8.0\n            laravel: 10.*\n          - php: 8.0\n            laravel: 11.*\n          - php: 8.1\n            laravel: 11.*\n          - php: 8.0\n            laravel: 12.*\n          - php: 8.1\n            laravel: 12.*\n          - php: 8.0\n            laravel: 13.*\n          - php: 8.1\n            laravel: 13.*\n          - php: 8.2\n            laravel: 13.*\n\n    name: PHP${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }}\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v1\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@v2\n        with:\n          php-version: ${{ matrix.php }}\n          extensions: mbstring json openssl\n          coverage: ${{ matrix.coverage }}\n          ini-values: memory_limit=-1\n\n      - name: Get composer cache directory\n        id: composer-cache\n        run: echo \"dir=$(composer config cache-files-dir)\" >> $GITHUB_OUTPUT\n\n      - name: Cache dependencies\n        uses: actions/cache@v3\n        with:\n          path: ${{ steps.composer-cache.outputs.dir }}\n          key: \"php-${{ matrix.php }}-laravel-${{ matrix.laravel }}-${{ matrix.stability }}-${{ hashFiles('**/composer.json') }}\"\n          restore-keys: \"php-${{ matrix.php }}-laravel-${{ matrix.laravel }}-${{ matrix.stability }}-${{ hashFiles('**/composer.json') }}\"\n\n      - name: Install dependencies\n        run: |\n          composer require \"illuminate/contracts:${{ matrix.laravel }}\" --no-interaction --no-progress --no-update\n          composer update --${{ matrix.stability }} --no-progress --prefer-dist --no-interaction\n\n      - name: Execute tests\n        run: composer test:ci\n\n      - name: Upload coverage\n        uses: codecov/codecov-action@v5\n        if: matrix.coverage == 'xdebug'\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          files: ./coverage.xml\n"
  },
  {
    "path": ".gitignore",
    "content": "/vendor\ncomposer.lock\nbuild\ncoverage.xml\n.phpunit.result.cache\n"
  },
  {
    "path": ".styleci.yml",
    "content": "preset: laravel\n\nenabled:\n  - no_useless_else\n  - unalign_double_arrow\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) Sean Tymon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "![jwt-auth-banner](https://cloud.githubusercontent.com/assets/1801923/9915273/119b9350-5cae-11e5-850b-c941cac60b32.png)\n\n[![PHPUnit](https://github.com/tymondesigns/jwt-auth/workflows/PHPUnit%20tests/badge.svg)](https://github.com/tymondesigns/jwt-auth/actions)\n[![Codecov branch](https://img.shields.io/codecov/c/github/tymondesigns/jwt-auth/develop.svg?style=flat-square&logo=codecov)](https://codecov.io/github/tymondesigns/jwt-auth)\n[![StyleCI](https://styleci.io/repos/23680678/shield?style=flat-square)](https://styleci.io/repos/23680678)\n[![Latest Version](http://img.shields.io/packagist/v/tymon/jwt-auth.svg?style=flat-square&logo=composer)](https://packagist.org/packages/tymon/jwt-auth)\n[![Latest Dev Version](https://img.shields.io/packagist/vpre/tymon/jwt-auth.svg?style=flat-square&logo=composer)](https://packagist.org/packages/tymon/jwt-auth#dev-develop)\n[![Monthly Downloads](https://img.shields.io/packagist/dm/tymon/jwt-auth.svg?style=flat-square&logo=composer)](https://packagist.org/packages/tymon/jwt-auth)\n\n## Documentation\n\n[jwt-auth.com](https://jwt-auth.com)\n\n-----------------------------------\n\n## Security\n\nIf you discover any security related issues, please email tymon148@gmail.com instead of using the issue tracker.\n\n## License\n\nThe MIT License (MIT)\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"tymon/jwt-auth\",\n    \"description\": \"JSON Web Token Authentication for Laravel and Lumen\",\n    \"keywords\": [\n        \"auth\",\n        \"authentication\",\n        \"json web token\",\n        \"jwt\",\n        \"laravel\"\n    ],\n    \"homepage\": \"https://github.com/tymondesigns/jwt-auth\",\n    \"support\": {\n        \"issues\": \"https://github.com/tymondesigns/jwt-auth/issues\",\n        \"source\": \"https://github.com/tymondesigns/jwt-auth\"\n    },\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Sean Tymon\",\n            \"email\": \"tymon148@gmail.com\",\n            \"homepage\": \"https://tymon.xyz\",\n            \"role\": \"Developer\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^8.0\",\n        \"illuminate/auth\": \"^9.0|^10.0|^11.0|^12.0|^13.0\",\n        \"illuminate/contracts\": \"^9.0|^10.0|^11.0|^12.0|^13.0\",\n        \"illuminate/http\": \"^9.0|^10.0|^11.0|^12.0|^13.0\",\n        \"illuminate/support\": \"^9.0|^10.0|^11.0|^12.0|^13.0\",\n        \"lcobucci/jwt\": \"^4.0|^5.0\",\n        \"nesbot/carbon\": \"^2.69|^3.0\"\n    },\n    \"require-dev\": {\n        \"illuminate/console\": \"^9.0|^10.0|^11.0|^12.0|^13.0\",\n        \"illuminate/database\": \"^9.0|^10.0|^11.0|^12.0|^13.0\",\n        \"illuminate/routing\": \"^9.0|^10.0|^11.0|^12.0|^13.0\",\n        \"mockery/mockery\": \"^1.6\",\n        \"phpunit/phpunit\": \"^9.4\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Tymon\\\\JWTAuth\\\\\": \"src/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Tymon\\\\JWTAuth\\\\Test\\\\\": \"tests/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-develop\": \"1.0-dev\",\n            \"dev-2.x\": \"2.0-dev\"\n        },\n        \"laravel\": {\n            \"aliases\": {\n                \"JWTAuth\": \"Tymon\\\\JWTAuth\\\\Facades\\\\JWTAuth\",\n                \"JWTFactory\": \"Tymon\\\\JWTAuth\\\\Facades\\\\JWTFactory\"\n            },\n            \"providers\": [\n                \"Tymon\\\\JWTAuth\\\\Providers\\\\LaravelServiceProvider\"\n            ]\n        }\n    },\n    \"config\": {\n        \"sort-packages\": true\n    },\n    \"prefer-stable\": true,\n    \"minimum-stability\": \"dev\",\n    \"scripts\": {\n        \"test\": \"phpunit --colors=always\",\n        \"test:ci\": \"composer test -- --verbose --coverage-text --coverage-clover=coverage.xml\"\n    }\n}\n"
  },
  {
    "path": "config/config.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | JWT Authentication Secret\n    |--------------------------------------------------------------------------\n    |\n    | Don't forget to set this in your .env file, as it will be used to sign\n    | your tokens. A helper command is provided for this:\n    | `php artisan jwt:secret`\n    |\n    | Note: This will be used for Symmetric algorithms only (HMAC),\n    | since RSA and ECDSA use a private/public key combo (See below).\n    |\n    */\n\n    'secret' => env('JWT_SECRET'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | JWT Authentication Keys\n    |--------------------------------------------------------------------------\n    |\n    | The algorithm you are using, will determine whether your tokens are\n    | signed with a random string (defined in `JWT_SECRET`) or using the\n    | following public & private keys.\n    |\n    | Symmetric Algorithms:\n    | HS256, HS384 & HS512 will use `JWT_SECRET`.\n    |\n    | Asymmetric Algorithms:\n    | RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below.\n    |\n    */\n\n    'keys' => [\n\n        /*\n        |--------------------------------------------------------------------------\n        | Public Key\n        |--------------------------------------------------------------------------\n        |\n        | A path or resource to your public key.\n        |\n        | E.g. 'file://path/to/public/key'\n        |\n        */\n\n        'public' => env('JWT_PUBLIC_KEY'),\n\n        /*\n        |--------------------------------------------------------------------------\n        | Private Key\n        |--------------------------------------------------------------------------\n        |\n        | A path or resource to your private key.\n        |\n        | E.g. 'file://path/to/private/key'\n        |\n        */\n\n        'private' => env('JWT_PRIVATE_KEY'),\n\n        /*\n        |--------------------------------------------------------------------------\n        | Passphrase\n        |--------------------------------------------------------------------------\n        |\n        | The passphrase for your private key. Can be null if none set.\n        |\n        */\n\n        'passphrase' => env('JWT_PASSPHRASE'),\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | JWT time to live\n    |--------------------------------------------------------------------------\n    |\n    | Specify the length of time (in minutes) that the token will be valid for.\n    | Defaults to 1 hour.\n    |\n    | You can also set this to null, to yield a never expiring token.\n    | Some people may want this behaviour for e.g. a mobile app.\n    | This is not particularly recommended, so make sure you have appropriate\n    | systems in place to revoke the token if necessary.\n    | Notice: If you set this to null you should remove 'exp' element from 'required_claims' list.\n    |\n    */\n\n    'ttl' => env('JWT_TTL', 60),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Refresh time to live\n    |--------------------------------------------------------------------------\n    |\n    | Specify the length of time (in minutes) that the token can be refreshed\n    | within. I.E. The user can refresh their token within a 2 week window of\n    | the original token being created until they must re-authenticate.\n    | Defaults to 2 weeks.\n    |\n    | You can also set this to null, to yield an infinite refresh time.\n    | Some may want this instead of never expiring tokens for e.g. a mobile app.\n    | This is not particularly recommended, so make sure you have appropriate\n    | systems in place to revoke the token if necessary.\n    |\n    */\n\n    'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),\n\n    /*\n    |--------------------------------------------------------------------------\n    | JWT hashing algorithm\n    |--------------------------------------------------------------------------\n    |\n    | Specify the hashing algorithm that will be used to sign the token.\n    |\n    */\n\n    'algo' => env('JWT_ALGO', Tymon\\JWTAuth\\Providers\\JWT\\Provider::ALGO_HS256),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Required Claims\n    |--------------------------------------------------------------------------\n    |\n    | Specify the required claims that must exist in any token.\n    | A TokenInvalidException will be thrown if any of these claims are not\n    | present in the payload.\n    |\n    */\n\n    'required_claims' => [\n        'iss',\n        'iat',\n        'exp',\n        'nbf',\n        'sub',\n        'jti',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Persistent Claims\n    |--------------------------------------------------------------------------\n    |\n    | Specify the claim keys to be persisted when refreshing a token.\n    | `sub` and `iat` will automatically be persisted, in\n    | addition to the these claims.\n    |\n    | Note: If a claim does not exist then it will be ignored.\n    |\n    */\n\n    'persistent_claims' => [\n        // 'foo',\n        // 'bar',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Lock Subject\n    |--------------------------------------------------------------------------\n    |\n    | This will determine whether a `prv` claim is automatically added to\n    | the token. The purpose of this is to ensure that if you have multiple\n    | authentication models e.g. `App\\User` & `App\\OtherPerson`, then we\n    | should prevent one authentication request from impersonating another,\n    | if 2 tokens happen to have the same id across the 2 different models.\n    |\n    | Under specific circumstances, you may want to disable this behaviour\n    | e.g. if you only have one authentication model, then you would save\n    | a little on token size.\n    |\n    */\n\n    'lock_subject' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Leeway\n    |--------------------------------------------------------------------------\n    |\n    | This property gives the jwt timestamp claims some \"leeway\".\n    | Meaning that if you have any unavoidable slight clock skew on\n    | any of your servers then this will afford you some level of cushioning.\n    |\n    | This applies to the claims `iat`, `nbf` and `exp`.\n    |\n    | Specify in seconds - only if you know you need it.\n    |\n    */\n\n    'leeway' => env('JWT_LEEWAY', 0),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Blacklist Enabled\n    |--------------------------------------------------------------------------\n    |\n    | In order to invalidate tokens, you must have the blacklist enabled.\n    | If you do not want or need this functionality, then set this to false.\n    |\n    */\n\n    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),\n\n    /*\n    | -------------------------------------------------------------------------\n    | Blacklist Grace Period\n    | -------------------------------------------------------------------------\n    |\n    | When multiple concurrent requests are made with the same JWT,\n    | it is possible that some of them fail, due to token regeneration\n    | on every request.\n    |\n    | Set grace period in seconds to prevent parallel request failure.\n    |\n    */\n\n    'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cookies encryption\n    |--------------------------------------------------------------------------\n    |\n    | By default Laravel encrypt cookies for security reason.\n    | If you decide to not decrypt cookies, you will have to configure Laravel\n    | to not encrypt your cookie token by adding its name into the $except\n    | array available in the middleware \"EncryptCookies\" provided by Laravel.\n    | see https://laravel.com/docs/master/responses#cookies-and-encryption\n    | for details.\n    |\n    | Set it to true if you want to decrypt cookies.\n    |\n    */\n\n    'decrypt_cookies' => false,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Providers\n    |--------------------------------------------------------------------------\n    |\n    | Specify the various providers used throughout the package.\n    |\n    */\n\n    'providers' => [\n\n        /*\n        |--------------------------------------------------------------------------\n        | JWT Provider\n        |--------------------------------------------------------------------------\n        |\n        | Specify the provider that is used to create and decode the tokens.\n        |\n        */\n\n        'jwt' => Tymon\\JWTAuth\\Providers\\JWT\\Lcobucci::class,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Authentication Provider\n        |--------------------------------------------------------------------------\n        |\n        | Specify the provider that is used to authenticate users.\n        |\n        */\n\n        'auth' => Tymon\\JWTAuth\\Providers\\Auth\\Illuminate::class,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Storage Provider\n        |--------------------------------------------------------------------------\n        |\n        | Specify the provider that is used to store tokens in the blacklist.\n        |\n        */\n\n        'storage' => Tymon\\JWTAuth\\Providers\\Storage\\Illuminate::class,\n\n    ],\n\n];\n"
  },
  {
    "path": "docs/auth-guard.md",
    "content": "## Methods\n\nThe following methods are available on the Auth guard instance.\n\n### Multiple Guards\n\nIf the newly created 'api' guard is not set as a default guard or you have defined multiple guards to handle authentication,\nyou should specify the guard when calling auth().\n\n```php\n  $token = auth('api')->attempt($credentials);\n```\n\n### attempt()\n\nAttempt to authenticate a user via some credentials.\n\n```php\n// Generate a token for the user if the credentials are valid\n$token = auth()->attempt($credentials);\n```\n\nThis will return either a jwt or `null`\n\n### login()\n\nLog a user in and return a jwt for them.\n\n```php\n// Get some user from somewhere\n$user = User::first();\n\n// Get the token\n$token = auth()->login($user);\n```\n\n### user()\n\nGet the currently authenticated user.\n\n```php\n// Get the currently authenticated user\n$user = auth()->user();\n```\n\nIf the user is not then authenticated, then `null` will be returned.\n\n### userOrFail()\n\nGet the currently authenticated user or throw an exception.\n\n```php\ntry {\n    $user = auth()->userOrFail();\n} catch (\\Tymon\\JWTAuth\\Exceptions\\UserNotDefinedException $e) {\n    // do something\n}\n\n```\n\nIf the user is not set, then a `Tymon\\JWTAuth\\Exceptions\\UserNotDefinedException` will be thrown\n\n### logout()\n\nLog the user out - which will invalidate the current token and unset the authenticated user.\n\n```php\nauth()->logout();\n\n// Pass true to force the token to be blacklisted \"forever\"\nauth()->logout(true);\n```\n\n### refresh()\n\nRefresh a token, which invalidates the current one\n\n```php\n$newToken = auth()->refresh();\n\n// Pass true as the first param to force the token to be blacklisted \"forever\".\n// The second parameter will reset the claims for the new token\n$newToken = auth()->refresh(true, true);\n```\n\n### invalidate()\n\nInvalidate the token (add it to the blacklist)\n\n```php\nauth()->invalidate();\n\n// Pass true as the first param to force the token to be blacklisted \"forever\".\nauth()->invalidate(true);\n```\n\n### tokenById()\n\nGet a token based on a given user's id.\n\n```php\n$token = auth()->tokenById(123);\n```\n\n### payload()\n\nGet the raw JWT payload\n\n```php\n$payload = auth()->payload();\n\n// then you can access the claims directly e.g.\n$payload->get('sub'); // = 123\n$payload['jti']; // = 'asfe4fq434asdf'\n$payload('exp') // = 123456\n$payload->toArray(); // = ['sub' => 123, 'exp' => 123456, 'jti' => 'asfe4fq434asdf'] etc\n```\n\n### validate()\n\nValidate a user's credentials\n\n```php\nif (auth()->validate($credentials)) {\n    // credentials are valid\n}\n```\n\n## More advanced usage\n\n### Adding custom claims\n\n```php\n$token = auth()->claims(['foo' => 'bar'])->attempt($credentials);\n```\n\n### Set the token explicitly\n\n```php\n$user = auth()->setToken('eyJhb...')->user();\n```\n\n### Set the request instance explicitly\n\n```php\n$user = auth()->setRequest($request)->user();\n```\n\n### Override the token ttl\n\n```php\n$token = auth()->setTTL(7200)->attempt($credentials);\n```\n"
  },
  {
    "path": "docs/configuration.md",
    "content": "Let's review some of the options in the `config/jwt.php` file that we published earlier.\nI won't go through all of the options here since [the file itself](https://github.com/tymondesigns/jwt-auth/blob/1.0.0-beta.2/config/config.php) is pretty well documented.\n\nFirst up is:\n\n```\n'secret' => env('JWT_SECRET'),\n```\n\nComing soon...\n"
  },
  {
    "path": "docs/exception-handling.md",
    "content": "Coming soon...\n"
  },
  {
    "path": "docs/index.md",
    "content": "JSON Web Token Authentication for Laravel & Lumen\n\n![jwt-auth-banner](https://cloud.githubusercontent.com/assets/1801923/9915273/119b9350-5cae-11e5-850b-c941cac60b32.png)\n"
  },
  {
    "path": "docs/laravel-installation.md",
    "content": "### Install via composer\n\nRun the following command to pull in the latest version:\n\n```bash\ncomposer require tymon/jwt-auth\n```\n\n-------------------------------------------------------------------------------\n\n### Add service provider ( Laravel 5.4 or below )\n\nAdd the service provider to the `providers` array in the `config/app.php` config file as follows:\n\n```php\n'providers' => [\n\n    ...\n\n    Tymon\\JWTAuth\\Providers\\LaravelServiceProvider::class,\n]\n```\n\n-------------------------------------------------------------------------------\n\n### Publish the config\n\nRun the following command to publish the package config file:\n\n```bash\nphp artisan vendor:publish --provider=\"Tymon\\JWTAuth\\Providers\\LaravelServiceProvider\"\n```\n\nYou should now have a `config/jwt.php` file that allows you to configure the basics of this package.\n\n-------------------------------------------------------------------------------\n\n### Generate secret key\n\nI have included a helper command to generate a key for you:\n\n```bash\nphp artisan jwt:secret\n```\n\nThis will update your `.env` file with something like `JWT_SECRET=foobar`\n\nIt is the key that will be used to sign your tokens. How that happens exactly will depend\non the algorithm that you choose to use.\n"
  },
  {
    "path": "docs/lumen-installation.md",
    "content": "### Install via composer\n\nRun the following command to pull in the latest version:\n\n```bash\ncomposer require tymon/jwt-auth\n```\n\n-------------------------------------------------------------------------------\n\n### Copy the config\n\nCopy the `config` file from `vendor/tymon/jwt-auth/config/config.php` to `config` folder of your Lumen application and rename it to `jwt.php`\n\nRegister your config by adding the following in the `bootstrap/app.php` before middleware declaration.\n\n```php\n$app->configure('jwt');\n```\n\n-------------------------------------------------------------------------------\n\n### Bootstrap file changes\n\nAdd the following snippet to the `bootstrap/app.php` file under the providers section as follows:\n\n```php\n// Uncomment this line\n$app->register(App\\Providers\\AuthServiceProvider::class);\n\n// Add this line\n$app->register(Tymon\\JWTAuth\\Providers\\LumenServiceProvider::class);\n```\n\nThen uncomment the `auth` middleware in the same file:\n\n```php\n$app->routeMiddleware([\n    'auth' => App\\Http\\Middleware\\Authenticate::class,\n]);\n```\n\n-------------------------------------------------------------------------------\n\n### Generate secret key\n\nI have included a helper command to generate a key for you:\n\n```bash\nphp artisan jwt:secret\n```\n\nThis will update your `.env` file with something like `JWT_SECRET=foobar`\n\nIt is the key that will be used to sign your tokens. How that happens exactly will depend\non the algorithm that you choose to use.\n"
  },
  {
    "path": "docs/quick-start.md",
    "content": "Before continuing, make sure you have installed the package as per the installation instructions for\n[Laravel](laravel-installation) or [Lumen](lumen-installation).\n\n### Update your User model\n\nFirstly you need to implement the `Tymon\\JWTAuth\\Contracts\\JWTSubject` contract on your User model,\nwhich requires that you implement the 2 methods `getJWTIdentifier()` and `getJWTCustomClaims()`.\n\nThe example below should give you an idea of how this could look. Obviously you should make any\nchanges, as necessary, to suit your own needs.\n\n```php\n<?php\n\nnamespace App;\n\nuse Tymon\\JWTAuth\\Contracts\\JWTSubject;\nuse Illuminate\\Notifications\\Notifiable;\nuse Illuminate\\Foundation\\Auth\\User as Authenticatable;\n\nclass User extends Authenticatable implements JWTSubject\n{\n    use Notifiable;\n\n    // Rest omitted for brevity\n\n    /**\n     * Get the identifier that will be stored in the subject claim of the JWT.\n     *\n     * @return mixed\n     */\n    public function getJWTIdentifier()\n    {\n        return $this->getKey();\n    }\n\n    /**\n     * Return a key value array, containing any custom claims to be added to the JWT.\n     *\n     * @return array\n     */\n    public function getJWTCustomClaims()\n    {\n        return [];\n    }\n}\n```\n\n### Configure Auth guard\n\n*Note: This will only work if you are using Laravel 5.2 and above.*\n\nInside the `config/auth.php` file you will need to make a few changes to configure Laravel\nto use the `jwt` guard to power your application authentication.\n\nMake the following changes to the file:\n\n```php\n'defaults' => [\n    'guard' => 'api',\n    'passwords' => 'users',\n],\n\n...\n\n'guards' => [\n    'api' => [\n        'driver' => 'jwt',\n        'provider' => 'users',\n    ],\n],\n```\n\nHere we are telling the `api` guard to use the `jwt` driver, and we are setting the `api` guard\nas the default.\n\nWe can now use Laravel's built in Auth system, with jwt-auth doing the work behind the scenes!\n\n### Add some basic authentication routes\n\nFirst let's add some routes in `routes/api.php` as follows:\n\n```php\nRoute::group([\n\n    'middleware' => 'api',\n    'prefix' => 'auth'\n\n], function ($router) {\n\n    Route::post('login', 'AuthController@login');\n    Route::post('logout', 'AuthController@logout');\n    Route::post('refresh', 'AuthController@refresh');\n    Route::post('me', 'AuthController@me');\n\n});\n```\n\n### Create the AuthController\n\nThen create the `AuthController`, either manually or by running the artisan command:\n\n```bash\nphp artisan make:controller AuthController\n```\n\nThen add the following:\n\n```php\n<?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Support\\Facades\\Auth;\nuse App\\Http\\Controllers\\Controller;\n\nclass AuthController extends Controller\n{\n    /**\n     * Create a new AuthController instance.\n     *\n     * @return void\n     */\n    public function __construct()\n    {\n        $this->middleware('auth:api', ['except' => ['login']]);\n    }\n\n    /**\n     * Get a JWT via given credentials.\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function login()\n    {\n        $credentials = request(['email', 'password']);\n\n        if (! $token = auth()->attempt($credentials)) {\n            return response()->json(['error' => 'Unauthorized'], 401);\n        }\n\n        return $this->respondWithToken($token);\n    }\n\n    /**\n     * Get the authenticated User.\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function me()\n    {\n        return response()->json(auth()->user());\n    }\n\n    /**\n     * Log the user out (Invalidate the token).\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function logout()\n    {\n        auth()->logout();\n\n        return response()->json(['message' => 'Successfully logged out']);\n    }\n\n    /**\n     * Refresh a token.\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function refresh()\n    {\n        return $this->respondWithToken(auth()->refresh());\n    }\n\n    /**\n     * Get the token array structure.\n     *\n     * @param  string $token\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondWithToken($token)\n    {\n        return response()->json([\n            'access_token' => $token,\n            'token_type' => 'bearer',\n            'expires_in' => auth()->factory()->getTTL() * 60\n        ]);\n    }\n}\n```\n\nYou should now be able to POST to the login endpoint (e.g. `http://example.dev/auth/login`) with some valid\ncredentials and see a response like:\n\n```json\n{\n    \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ\",\n    \"token_type\": \"bearer\",\n    \"expires_in\": 3600\n}\n```\n\nThis token can then be used to make authenticated requests to your application.\n\n### Authenticated requests\n\nThere are a number of ways to send the token via http:\n\n**Authorization header**\n\n`Authorization: Bearer eyJhbGciOiJIUzI1NiI...`\n\n**Query string parameter**\n\n`http://example.dev/me?token=eyJhbGciOiJIUzI1NiI...`\n\n**Post parameter**\n\n**Cookies**\n\n**Laravel route parameter**\n"
  },
  {
    "path": "docs/resources.md",
    "content": "- [The Anatomy of a JSON Web Token](https://scotch.io/tutorials/the-anatomy-of-a-json-web-token)\n- [jwt.io](https://jwt.io/)\n\nOver the last couple of years, the community has provided some great tutorials and packages that\nhave helped people get up and running with jwt-auth. So it's only right that I post some of them here.\n\nComing soon...\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: jwt-auth\npages:\n    - Home: index.md\n    - Laravel Installation: laravel-installation.md\n    - Lumen Installation (incomplete): lumen-installation.md\n    - Quick start: quick-start.md\n    - Auth guard: auth-guard.md\n    - Configuration: configuration.md\n    - Exception Handling: exception-handling.md\n    - Resources: resources.md\ntheme: readthedocs\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    backupGlobals=\"false\"\n    backupStaticAttributes=\"false\"\n    beStrictAboutTestsThatDoNotTestAnything=\"false\"\n    beStrictAboutOutputDuringTests=\"true\"\n    bootstrap=\"vendor/autoload.php\"\n    colors=\"true\"\n    convertErrorsToExceptions=\"true\"\n    convertNoticesToExceptions=\"true\"\n    convertWarningsToExceptions=\"true\"\n    failOnRisky=\"true\"\n    failOnWarning=\"true\"\n    processIsolation=\"false\"\n    stopOnError=\"false\"\n    stopOnFailure=\"false\"\n    verbose=\"true\"\n    xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/9.3/phpunit.xsd\"\n>\n  <coverage>\n    <include>\n      <directory suffix=\".php\">src/</directory>\n    </include>\n    <exclude>\n      <file>src/Providers/AbstractServiceProvider.php</file>\n      <file>src/Providers/LaravelServiceProvider.php</file>\n      <file>src/Providers/LumenServiceProvider.php</file>\n      <directory suffix=\".php\">src/Facades/</directory>\n      <directory suffix=\".php\">src/Console/</directory>\n    </exclude>\n    <report>\n      <clover outputFile=\"build/logs/clover.xml\"/>\n      <html outputDirectory=\"build/coverage\"/>\n      <text outputFile=\"build/coverage.txt\"/>\n    </report>\n  </coverage>\n  <testsuites>\n    <testsuite name=\"jwt-auth Test Suite\">\n      <directory>tests</directory>\n    </testsuite>\n  </testsuites>\n  <logging>\n    <junit outputFile=\"build/report.junit.xml\"/>\n  </logging>\n</phpunit>\n"
  },
  {
    "path": "src/Blacklist.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Storage;\nuse Tymon\\JWTAuth\\Support\\Utils;\n\nclass Blacklist\n{\n    /**\n     * The storage.\n     *\n     * @var \\Tymon\\JWTAuth\\Contracts\\Providers\\Storage\n     */\n    protected $storage;\n\n    /**\n     * The grace period when a token is blacklisted. In seconds.\n     *\n     * @var int\n     */\n    protected $gracePeriod = 0;\n\n    /**\n     * Number of minutes from issue date in which a JWT can be refreshed.\n     *\n     * @var int\n     */\n    protected $refreshTTL = 20160;\n\n    /**\n     * The unique key held within the blacklist.\n     *\n     * @var string\n     */\n    protected $key = 'jti';\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\Providers\\Storage  $storage\n     * @return void\n     */\n    public function __construct(Storage $storage)\n    {\n        $this->storage = $storage;\n    }\n\n    /**\n     * Add the token (jti claim) to the blacklist.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return bool\n     */\n    public function add(Payload $payload)\n    {\n        // if there is no exp claim then add the jwt to\n        // the blacklist indefinitely\n        if (! $payload->hasKey('exp')) {\n            return $this->addForever($payload);\n        }\n\n        // if we have already added this token to the blacklist\n        if (! empty($this->storage->get($this->getKey($payload)))) {\n            return true;\n        }\n\n        $this->storage->add(\n            $this->getKey($payload),\n            ['valid_until' => $this->getGraceTimestamp()],\n            $this->getMinutesUntilExpired($payload)\n        );\n\n        return true;\n    }\n\n    /**\n     * Get the number of minutes until the token expiry.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return int\n     */\n    protected function getMinutesUntilExpired(Payload $payload)\n    {\n        $exp = Utils::timestamp($payload['exp']);\n        $iat = Utils::timestamp($payload['iat']);\n\n        // get the latter of the two expiration dates and find\n        // the number of minutes until the expiration date,\n        // plus 1 minute to avoid overlap\n        $expiration = $exp->max($iat->addMinutes($this->refreshTTL))->addMinute();\n\n        $minutes = method_exists($expiration, 'diffInRealMinutes')\n            ? $expiration->diffInRealMinutes()\n            : $expiration->diffInUTCMinutes();\n\n        return (int) ceil(abs($minutes));\n    }\n\n    /**\n     * Add the token (jti claim) to the blacklist indefinitely.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return bool\n     */\n    public function addForever(Payload $payload)\n    {\n        $this->storage->forever($this->getKey($payload), 'forever');\n\n        return true;\n    }\n\n    /**\n     * Determine whether the token has been blacklisted.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return bool\n     */\n    public function has(Payload $payload)\n    {\n        $val = $this->storage->get($this->getKey($payload));\n\n        // exit early if the token was blacklisted forever,\n        if ($val === 'forever') {\n            return true;\n        }\n\n        // check whether the expiry + grace has past\n        return ! empty($val) && ! Utils::isFuture($val['valid_until']);\n    }\n\n    /**\n     * Remove the token (jti claim) from the blacklist.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return bool\n     */\n    public function remove(Payload $payload)\n    {\n        return $this->storage->destroy($this->getKey($payload));\n    }\n\n    /**\n     * Remove all tokens from the blacklist.\n     *\n     * @return bool\n     */\n    public function clear()\n    {\n        $this->storage->flush();\n\n        return true;\n    }\n\n    /**\n     * Get the timestamp when the blacklist comes into effect\n     * This defaults to immediate (0 seconds).\n     *\n     * @return int\n     */\n    protected function getGraceTimestamp()\n    {\n        return Utils::now()->addSeconds($this->gracePeriod)->getTimestamp();\n    }\n\n    /**\n     * Set the grace period.\n     *\n     * @param  int  $gracePeriod\n     * @return $this\n     */\n    public function setGracePeriod($gracePeriod)\n    {\n        $this->gracePeriod = (int) $gracePeriod;\n\n        return $this;\n    }\n\n    /**\n     * Get the grace period.\n     *\n     * @return int\n     */\n    public function getGracePeriod()\n    {\n        return $this->gracePeriod;\n    }\n\n    /**\n     * Get the unique key held within the blacklist.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return mixed\n     */\n    public function getKey(Payload $payload)\n    {\n        return $payload($this->key);\n    }\n\n    /**\n     * Set the unique key held within the blacklist.\n     *\n     * @param  string  $key\n     * @return $this\n     */\n    public function setKey($key)\n    {\n        $this->key = value($key);\n\n        return $this;\n    }\n\n    /**\n     * Set the refresh time limit.\n     *\n     * @param  int  $ttl\n     * @return $this\n     */\n    public function setRefreshTTL($ttl)\n    {\n        $this->refreshTTL = (int) $ttl;\n\n        return $this;\n    }\n\n    /**\n     * Get the refresh time limit.\n     *\n     * @return int\n     */\n    public function getRefreshTTL()\n    {\n        return $this->refreshTTL;\n    }\n}\n"
  },
  {
    "path": "src/Claims/Audience.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nclass Audience extends Claim\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'aud';\n}\n"
  },
  {
    "path": "src/Claims/Claim.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Contracts\\Support\\Jsonable;\nuse JsonSerializable;\nuse Tymon\\JWTAuth\\Contracts\\Claim as ClaimContract;\n\nabstract class Claim implements Arrayable, ClaimContract, Jsonable, JsonSerializable\n{\n    /**\n     * The claim name.\n     *\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * The claim value.\n     *\n     * @var mixed\n     */\n    private $value;\n\n    /**\n     * @param  mixed  $value\n     * @return void\n     */\n    public function __construct($value)\n    {\n        $this->setValue($value);\n    }\n\n    /**\n     * Set the claim value, and call a validate method.\n     *\n     * @param  mixed  $value\n     * @return $this\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\InvalidClaimException\n     */\n    public function setValue($value)\n    {\n        $this->value = $this->validateCreate($value);\n\n        return $this;\n    }\n\n    /**\n     * Get the claim value.\n     *\n     * @return mixed\n     */\n    public function getValue()\n    {\n        return $this->value;\n    }\n\n    /**\n     * Set the claim name.\n     *\n     * @param  string  $name\n     * @return $this\n     */\n    public function setName($name)\n    {\n        $this->name = $name;\n\n        return $this;\n    }\n\n    /**\n     * Get the claim name.\n     *\n     * @return string\n     */\n    public function getName()\n    {\n        return $this->name;\n    }\n\n    /**\n     * Validate the claim in a standalone Claim context.\n     *\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function validateCreate($value)\n    {\n        return $value;\n    }\n\n    /**\n     * Validate the Claim within a Payload context.\n     *\n     * @return bool\n     */\n    public function validatePayload()\n    {\n        return $this->getValue();\n    }\n\n    /**\n     * Validate the Claim within a refresh context.\n     *\n     * @param  int  $refreshTTL\n     * @return bool\n     */\n    public function validateRefresh($refreshTTL)\n    {\n        return $this->getValue();\n    }\n\n    /**\n     * Checks if the value matches the claim.\n     *\n     * @param  mixed  $value\n     * @param  bool  $strict\n     * @return bool\n     */\n    public function matches($value, $strict = true)\n    {\n        return $strict ? $this->value === $value : $this->value == $value;\n    }\n\n    /**\n     * Convert the object into something JSON serializable.\n     *\n     * @return array\n     */\n    #[\\ReturnTypeWillChange]\n    public function jsonSerialize(): mixed\n    {\n        return $this->toArray();\n    }\n\n    /**\n     * Build a key value array comprising of the claim name and value.\n     *\n     * @return array\n     */\n    public function toArray()\n    {\n        return [$this->getName() => $this->getValue()];\n    }\n\n    /**\n     * Get the claim as JSON.\n     *\n     * @param  int  $options\n     * @return string\n     */\n    public function toJson($options = JSON_UNESCAPED_SLASHES)\n    {\n        return json_encode($this->toArray(), $options);\n    }\n\n    /**\n     * Get the payload as a string.\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->toJson();\n    }\n}\n"
  },
  {
    "path": "src/Claims/Collection.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nuse Illuminate\\Support\\Collection as IlluminateCollection;\nuse Illuminate\\Support\\Str;\n\nclass Collection extends IlluminateCollection\n{\n    /**\n     * Create a new collection.\n     *\n     * @param  mixed  $items\n     * @return void\n     */\n    public function __construct($items = [])\n    {\n        parent::__construct($this->getArrayableItems($items));\n    }\n\n    /**\n     * Get a Claim instance by it's unique name.\n     *\n     * @param  string  $name\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return \\Tymon\\JWTAuth\\Claims\\Claim\n     */\n    public function getByClaimName($name, ?callable $callback = null, $default = null)\n    {\n        return $this->filter(function (Claim $claim) use ($name) {\n            return $claim->getName() === $name;\n        })->first($callback, $default);\n    }\n\n    /**\n     * Validate each claim under a given context.\n     *\n     * @param  string  $context\n     * @return $this\n     */\n    public function validate($context = 'payload')\n    {\n        $args = func_get_args();\n        array_shift($args);\n\n        $this->each(function ($claim) use ($context, $args) {\n            call_user_func_array(\n                [$claim, 'validate'.Str::ucfirst($context)],\n                $args\n            );\n        });\n\n        return $this;\n    }\n\n    /**\n     * Determine if the Collection contains all of the given keys.\n     *\n     * @param  mixed  $claims\n     * @return bool\n     */\n    public function hasAllClaims($claims)\n    {\n        return count($claims) && (new static($claims))->diff($this->keys())->isEmpty();\n    }\n\n    /**\n     * Get the claims as key/val array.\n     *\n     * @return array\n     */\n    public function toPlainArray()\n    {\n        return $this->map(function (Claim $claim) {\n            return $claim->getValue();\n        })->toArray();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function getArrayableItems($items)\n    {\n        return $this->sanitizeClaims($items);\n    }\n\n    /**\n     * Ensure that the given claims array is keyed by the claim name.\n     *\n     * @param  mixed  $items\n     * @return array\n     */\n    private function sanitizeClaims($items)\n    {\n        $claims = [];\n        foreach ($items as $key => $value) {\n            if (! is_string($key) && $value instanceof Claim) {\n                $key = $value->getName();\n            }\n\n            $claims[$key] = $value;\n        }\n\n        return $claims;\n    }\n}\n"
  },
  {
    "path": "src/Claims/Custom.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nclass Custom extends Claim\n{\n    /**\n     * @param  string  $name\n     * @param  mixed  $value\n     * @return void\n     */\n    public function __construct($name, $value)\n    {\n        parent::__construct($value);\n        $this->setName($name);\n    }\n}\n"
  },
  {
    "path": "src/Claims/DatetimeTrait.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nuse DateInterval;\nuse DateTimeInterface;\nuse Tymon\\JWTAuth\\Exceptions\\InvalidClaimException;\nuse Tymon\\JWTAuth\\Support\\Utils;\n\ntrait DatetimeTrait\n{\n    /**\n     * Time leeway in seconds.\n     *\n     * @var int\n     */\n    protected $leeway = 0;\n\n    /**\n     * Set the claim value, and call a validate method.\n     *\n     * @param  mixed  $value\n     * @return $this\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\InvalidClaimException\n     */\n    public function setValue($value)\n    {\n        if ($value instanceof DateInterval) {\n            $value = Utils::now()->add($value);\n        }\n\n        if ($value instanceof DateTimeInterface) {\n            $value = $value->getTimestamp();\n        }\n\n        return parent::setValue($value);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function validateCreate($value)\n    {\n        if (! is_numeric($value)) {\n            throw new InvalidClaimException($this);\n        }\n\n        return $value;\n    }\n\n    /**\n     * Determine whether the value is in the future.\n     *\n     * @param  mixed  $value\n     * @return bool\n     */\n    protected function isFuture($value)\n    {\n        return Utils::isFuture($value, $this->leeway);\n    }\n\n    /**\n     * Determine whether the value is in the past.\n     *\n     * @param  mixed  $value\n     * @return bool\n     */\n    protected function isPast($value)\n    {\n        return Utils::isPast($value, $this->leeway);\n    }\n\n    /**\n     * Set the leeway in seconds.\n     *\n     * @param  int  $leeway\n     * @return $this\n     */\n    public function setLeeway($leeway)\n    {\n        $this->leeway = $leeway;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Claims/Expiration.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nuse Tymon\\JWTAuth\\Exceptions\\TokenExpiredException;\n\nclass Expiration extends Claim\n{\n    use DatetimeTrait;\n\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'exp';\n\n    /**\n     * {@inheritdoc}\n     */\n    public function validatePayload()\n    {\n        if ($this->isPast($this->getValue())) {\n            throw new TokenExpiredException('Token has expired');\n        }\n    }\n}\n"
  },
  {
    "path": "src/Claims/Factory.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Str;\nuse Tymon\\JWTAuth\\Support\\Utils;\n\nclass Factory\n{\n    /**\n     * The request.\n     *\n     * @var \\Illuminate\\Http\\Request\n     */\n    protected $request;\n\n    /**\n     * The TTL.\n     *\n     * @var int\n     */\n    protected $ttl = 60;\n\n    /**\n     * Time leeway in seconds.\n     *\n     * @var int\n     */\n    protected $leeway = 0;\n\n    /**\n     * The classes map.\n     *\n     * @var array\n     */\n    private $classMap = [\n        'aud' => Audience::class,\n        'exp' => Expiration::class,\n        'iat' => IssuedAt::class,\n        'iss' => Issuer::class,\n        'jti' => JwtId::class,\n        'nbf' => NotBefore::class,\n        'sub' => Subject::class,\n    ];\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return void\n     */\n    public function __construct(Request $request)\n    {\n        $this->request = $request;\n    }\n\n    /**\n     * Get the instance of the claim when passing the name and value.\n     *\n     * @param  string  $name\n     * @param  mixed  $value\n     * @return \\Tymon\\JWTAuth\\Claims\\Claim\n     */\n    public function get($name, $value)\n    {\n        if ($this->has($name)) {\n            $claim = new $this->classMap[$name]($value);\n\n            return method_exists($claim, 'setLeeway') ?\n                $claim->setLeeway($this->leeway) :\n                $claim;\n        }\n\n        return new Custom($name, $value);\n    }\n\n    /**\n     * Check whether the claim exists.\n     *\n     * @param  string  $name\n     * @return bool\n     */\n    public function has($name)\n    {\n        return array_key_exists($name, $this->classMap);\n    }\n\n    /**\n     * Generate the initial value and return the Claim instance.\n     *\n     * @param  string  $name\n     * @return \\Tymon\\JWTAuth\\Claims\\Claim\n     */\n    public function make($name)\n    {\n        return $this->get($name, $this->$name());\n    }\n\n    /**\n     * Get the Issuer (iss) claim.\n     *\n     * @return string\n     */\n    public function iss()\n    {\n        return $this->request->url();\n    }\n\n    /**\n     * Get the Issued At (iat) claim.\n     *\n     * @return int\n     */\n    public function iat()\n    {\n        return Utils::now()->getTimestamp();\n    }\n\n    /**\n     * Get the Expiration (exp) claim.\n     *\n     * @return int\n     */\n    public function exp()\n    {\n        return Utils::now()->addMinutes($this->ttl)->getTimestamp();\n    }\n\n    /**\n     * Get the Not Before (nbf) claim.\n     *\n     * @return int\n     */\n    public function nbf()\n    {\n        return Utils::now()->getTimestamp();\n    }\n\n    /**\n     * Get the JWT Id (jti) claim.\n     *\n     * @return string\n     */\n    public function jti()\n    {\n        return Str::random();\n    }\n\n    /**\n     * Add a new claim mapping.\n     *\n     * @param  string  $name\n     * @param  string  $classPath\n     * @return $this\n     */\n    public function extend($name, $classPath)\n    {\n        $this->classMap[$name] = $classPath;\n\n        return $this;\n    }\n\n    /**\n     * Set the request instance.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return $this\n     */\n    public function setRequest(Request $request)\n    {\n        $this->request = $request;\n\n        return $this;\n    }\n\n    /**\n     * Set the token ttl (in minutes).\n     *\n     * @param  int  $ttl\n     * @return $this\n     */\n    public function setTTL($ttl)\n    {\n        $this->ttl = (int) $ttl;\n\n        return $this;\n    }\n\n    /**\n     * Get the token ttl.\n     *\n     * @return int\n     */\n    public function getTTL()\n    {\n        return $this->ttl;\n    }\n\n    /**\n     * Set the leeway in seconds.\n     *\n     * @param  int  $leeway\n     * @return $this\n     */\n    public function setLeeway($leeway)\n    {\n        $this->leeway = (int) $leeway;\n\n        return $this;\n    }\n\n    /**\n     * Get the leeway in seconds.\n     *\n     * @return int\n     */\n    public function getLeeway()\n    {\n        return $this->leeway;\n    }\n}\n"
  },
  {
    "path": "src/Claims/IssuedAt.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nuse Tymon\\JWTAuth\\Exceptions\\InvalidClaimException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenExpiredException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\n\nclass IssuedAt extends Claim\n{\n    use DatetimeTrait {\n        validateCreate as commonValidateCreate;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'iat';\n\n    /**\n     * {@inheritdoc}\n     */\n    public function validateCreate($value)\n    {\n        $this->commonValidateCreate($value);\n\n        if ($this->isFuture($value)) {\n            throw new InvalidClaimException($this);\n        }\n\n        return $value;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function validatePayload()\n    {\n        if ($this->isFuture($this->getValue())) {\n            throw new TokenInvalidException('Issued At (iat) timestamp cannot be in the future');\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function validateRefresh($refreshTTL)\n    {\n        if ($this->isPast($this->getValue() + $refreshTTL * 60)) {\n            throw new TokenExpiredException('Token has expired and can no longer be refreshed');\n        }\n    }\n}\n"
  },
  {
    "path": "src/Claims/Issuer.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nclass Issuer extends Claim\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'iss';\n}\n"
  },
  {
    "path": "src/Claims/JwtId.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nclass JwtId extends Claim\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'jti';\n}\n"
  },
  {
    "path": "src/Claims/NotBefore.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\n\nclass NotBefore extends Claim\n{\n    use DatetimeTrait;\n\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'nbf';\n\n    /**\n     * {@inheritdoc}\n     */\n    public function validatePayload()\n    {\n        if ($this->isFuture($this->getValue())) {\n            throw new TokenInvalidException('Not Before (nbf) timestamp cannot be in the future');\n        }\n    }\n}\n"
  },
  {
    "path": "src/Claims/Subject.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Claims;\n\nclass Subject extends Claim\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'sub';\n}\n"
  },
  {
    "path": "src/Console/JWTGenerateSecretCommand.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Str;\n\nclass JWTGenerateSecretCommand extends Command\n{\n    /**\n     * The console command signature.\n     *\n     * @var string\n     */\n    protected $signature = 'jwt:secret\n        {--s|show : Display the key instead of modifying files.}\n        {--always-no : Skip generating key if it already exists.}\n        {--f|force : Skip confirmation when overwriting an existing key.}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Set the JWTAuth secret key used to sign the tokens';\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $key = Str::random(64);\n\n        if ($this->option('show')) {\n            $this->comment($key);\n\n            return;\n        }\n\n        if (file_exists($path = $this->envPath()) === false) {\n            return $this->displayKey($key);\n        }\n\n        if (Str::contains(file_get_contents($path), 'JWT_SECRET') === false) {\n            // create new entry\n            file_put_contents($path, PHP_EOL.\"JWT_SECRET=$key\".PHP_EOL, FILE_APPEND);\n        } else {\n            if ($this->option('always-no')) {\n                $this->comment('Secret key already exists. Skipping...');\n\n                return;\n            }\n\n            if ($this->isConfirmed() === false) {\n                $this->comment('Phew... No changes were made to your secret key.');\n\n                return;\n            }\n\n            // update existing entry\n            file_put_contents($path, str_replace(\n                'JWT_SECRET='.$this->laravel['config']['jwt.secret'],\n                'JWT_SECRET='.$key, file_get_contents($path)\n            ));\n        }\n\n        $this->displayKey($key);\n    }\n\n    /**\n     * Display the key.\n     *\n     * @param  string  $key\n     * @return void\n     */\n    protected function displayKey($key)\n    {\n        $this->laravel['config']['jwt.secret'] = $key;\n\n        $this->info(\"jwt-auth secret [$key] set successfully.\");\n    }\n\n    /**\n     * Check if the modification is confirmed.\n     *\n     * @return bool\n     */\n    protected function isConfirmed()\n    {\n        return $this->option('force') ? true : $this->confirm(\n            'This will invalidate all existing tokens. Are you sure you want to override the secret key?'\n        );\n    }\n\n    /**\n     * Get the .env file path.\n     *\n     * @return string\n     */\n    protected function envPath()\n    {\n        if (method_exists($this->laravel, 'environmentFilePath')) {\n            return $this->laravel->environmentFilePath();\n        }\n\n        // check if laravel version Less than 5.4.17\n        if (version_compare($this->laravel->version(), '5.4.17', '<')) {\n            return $this->laravel->basePath().DIRECTORY_SEPARATOR.'.env';\n        }\n\n        return $this->laravel->basePath('.env');\n    }\n}\n"
  },
  {
    "path": "src/Contracts/Claim.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Contracts;\n\ninterface Claim\n{\n    /**\n     * Set the claim value, and call a validate method.\n     *\n     * @param  mixed  $value\n     * @return $this\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\InvalidClaimException\n     */\n    public function setValue($value);\n\n    /**\n     * Get the claim value.\n     *\n     * @return mixed\n     */\n    public function getValue();\n\n    /**\n     * Set the claim name.\n     *\n     * @param  string  $name\n     * @return $this\n     */\n    public function setName($name);\n\n    /**\n     * Get the claim name.\n     *\n     * @return string\n     */\n    public function getName();\n\n    /**\n     * Validate the Claim value.\n     *\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function validateCreate($value);\n}\n"
  },
  {
    "path": "src/Contracts/Http/Parser.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Contracts\\Http;\n\nuse Illuminate\\Http\\Request;\n\ninterface Parser\n{\n    /**\n     * Parse the request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    public function parse(Request $request);\n}\n"
  },
  {
    "path": "src/Contracts/JWTSubject.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Contracts;\n\ninterface JWTSubject\n{\n    /**\n     * Get the identifier that will be stored in the subject claim of the JWT.\n     *\n     * @return mixed\n     */\n    public function getJWTIdentifier();\n\n    /**\n     * Return a key value array, containing any custom claims to be added to the JWT.\n     *\n     * @return array\n     */\n    public function getJWTCustomClaims();\n}\n"
  },
  {
    "path": "src/Contracts/Providers/Auth.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Contracts\\Providers;\n\ninterface Auth\n{\n    /**\n     * Check a user's credentials.\n     *\n     * @param  array  $credentials\n     * @return mixed\n     */\n    public function byCredentials(array $credentials);\n\n    /**\n     * Authenticate a user via the id.\n     *\n     * @param  mixed  $id\n     * @return mixed\n     */\n    public function byId($id);\n\n    /**\n     * Get the currently authenticated user.\n     *\n     * @return mixed\n     */\n    public function user();\n}\n"
  },
  {
    "path": "src/Contracts/Providers/JWT.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Contracts\\Providers;\n\ninterface JWT\n{\n    /**\n     * @param  array  $payload\n     * @return string\n     */\n    public function encode(array $payload);\n\n    /**\n     * @param  string  $token\n     * @return array\n     */\n    public function decode($token);\n}\n"
  },
  {
    "path": "src/Contracts/Providers/Storage.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Contracts\\Providers;\n\ninterface Storage\n{\n    /**\n     * @param  string  $key\n     * @param  mixed  $value\n     * @param  int  $minutes\n     * @return void\n     */\n    public function add($key, $value, $minutes);\n\n    /**\n     * @param  string  $key\n     * @param  mixed  $value\n     * @return void\n     */\n    public function forever($key, $value);\n\n    /**\n     * @param  string  $key\n     * @return mixed\n     */\n    public function get($key);\n\n    /**\n     * @param  string  $key\n     * @return bool\n     */\n    public function destroy($key);\n\n    /**\n     * @return void\n     */\n    public function flush();\n}\n"
  },
  {
    "path": "src/Contracts/Validator.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Contracts;\n\ninterface Validator\n{\n    /**\n     * Perform some checks on the value.\n     *\n     * @param  mixed  $value\n     * @return void\n     */\n    public function check($value);\n\n    /**\n     * Helper function to return a boolean.\n     *\n     * @param  array  $value\n     * @return bool\n     */\n    public function isValid($value);\n}\n"
  },
  {
    "path": "src/Exceptions/InvalidClaimException.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Exceptions;\n\nuse Exception;\nuse Tymon\\JWTAuth\\Claims\\Claim;\n\nclass InvalidClaimException extends JWTException\n{\n    /**\n     * Constructor.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Claim  $claim\n     * @param  int  $code\n     * @param  \\Exception|null  $previous\n     * @return void\n     */\n    public function __construct(Claim $claim, $code = 0, ?Exception $previous = null)\n    {\n        parent::__construct('Invalid value provided for claim ['.$claim->getName().']', $code, $previous);\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/JWTException.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Exceptions;\n\nuse Exception;\n\nclass JWTException extends Exception\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $message = 'An error occurred';\n}\n"
  },
  {
    "path": "src/Exceptions/PayloadException.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Exceptions;\n\nclass PayloadException extends JWTException\n{\n    //\n}\n"
  },
  {
    "path": "src/Exceptions/TokenBlacklistedException.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Exceptions;\n\nclass TokenBlacklistedException extends TokenInvalidException\n{\n    //\n}\n"
  },
  {
    "path": "src/Exceptions/TokenExpiredException.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Exceptions;\n\nclass TokenExpiredException extends JWTException\n{\n    //\n}\n"
  },
  {
    "path": "src/Exceptions/TokenInvalidException.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Exceptions;\n\nclass TokenInvalidException extends JWTException\n{\n    //\n}\n"
  },
  {
    "path": "src/Exceptions/UserNotDefinedException.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Exceptions;\n\nclass UserNotDefinedException extends JWTException\n{\n    //\n}\n"
  },
  {
    "path": "src/Facades/JWTAuth.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Facades;\n\nuse Illuminate\\Support\\Facades\\Facade;\n\nclass JWTAuth extends Facade\n{\n    /**\n     * Get the registered name of the component.\n     *\n     * @return string\n     */\n    protected static function getFacadeAccessor()\n    {\n        return 'tymon.jwt.auth';\n    }\n}\n"
  },
  {
    "path": "src/Facades/JWTFactory.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Facades;\n\nuse Illuminate\\Support\\Facades\\Facade;\n\nclass JWTFactory extends Facade\n{\n    /**\n     * Get the registered name of the component.\n     *\n     * @return string\n     */\n    protected static function getFacadeAccessor()\n    {\n        return 'tymon.jwt.payload.factory';\n    }\n}\n"
  },
  {
    "path": "src/Facades/JWTProvider.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Facades;\n\nuse Illuminate\\Support\\Facades\\Facade;\n\nclass JWTProvider extends Facade\n{\n    /**\n     * Get the registered name of the component.\n     *\n     * @return string\n     */\n    protected static function getFacadeAccessor()\n    {\n        return 'tymon.jwt.provider.jwt';\n    }\n}\n"
  },
  {
    "path": "src/Factory.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse Tymon\\JWTAuth\\Claims\\Claim;\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Factory as ClaimFactory;\nuse Tymon\\JWTAuth\\Support\\CustomClaims;\nuse Tymon\\JWTAuth\\Support\\RefreshFlow;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass Factory\n{\n    use CustomClaims, RefreshFlow;\n\n    /**\n     * The claim factory.\n     *\n     * @var \\Tymon\\JWTAuth\\Claims\\Factory\n     */\n    protected $claimFactory;\n\n    /**\n     * The validator.\n     *\n     * @var \\Tymon\\JWTAuth\\Validators\\PayloadValidator\n     */\n    protected $validator;\n\n    /**\n     * The default claims.\n     *\n     * @var array\n     */\n    protected $defaultClaims = [\n        'iss',\n        'iat',\n        'exp',\n        'nbf',\n        'jti',\n    ];\n\n    /**\n     * The claims collection.\n     *\n     * @var \\Tymon\\JWTAuth\\Claims\\Collection\n     */\n    protected $claims;\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Factory  $claimFactory\n     * @param  \\Tymon\\JWTAuth\\Validators\\PayloadValidator  $validator\n     * @return void\n     */\n    public function __construct(ClaimFactory $claimFactory, PayloadValidator $validator)\n    {\n        $this->claimFactory = $claimFactory;\n        $this->validator = $validator;\n        $this->claims = new Collection;\n    }\n\n    /**\n     * Create the Payload instance.\n     *\n     * @param  bool  $resetClaims\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    public function make($resetClaims = false)\n    {\n        if ($resetClaims) {\n            $this->emptyClaims();\n        }\n\n        return $this->withClaims($this->buildClaimsCollection());\n    }\n\n    /**\n     * Empty the claims collection.\n     *\n     * @return $this\n     */\n    public function emptyClaims()\n    {\n        $this->claims = new Collection;\n\n        return $this;\n    }\n\n    /**\n     * Add an array of claims to the Payload.\n     *\n     * @param  array  $claims\n     * @return $this\n     */\n    protected function addClaims(array $claims)\n    {\n        foreach ($claims as $name => $value) {\n            $this->addClaim($name, $value);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Add a claim to the Payload.\n     *\n     * @param  string  $name\n     * @param  mixed  $value\n     * @return $this\n     */\n    protected function addClaim($name, $value)\n    {\n        $this->claims->put($name, $value);\n\n        return $this;\n    }\n\n    /**\n     * Build the default claims.\n     *\n     * @return $this\n     */\n    protected function buildClaims()\n    {\n        // remove the exp claim if it exists and the ttl is null\n        if ($this->claimFactory->getTTL() === null && $key = array_search('exp', $this->defaultClaims)) {\n            unset($this->defaultClaims[$key]);\n        }\n\n        // add the default claims\n        foreach ($this->defaultClaims as $claim) {\n            $this->addClaim($claim, $this->claimFactory->make($claim));\n        }\n\n        // add custom claims on top, allowing them to overwrite defaults\n        return $this->addClaims($this->getCustomClaims());\n    }\n\n    /**\n     * Build out the Claim DTO's.\n     *\n     * @return \\Tymon\\JWTAuth\\Claims\\Collection\n     */\n    protected function resolveClaims()\n    {\n        return $this->claims->map(function ($value, $name) {\n            return $value instanceof Claim ? $value : $this->claimFactory->get($name, $value);\n        });\n    }\n\n    /**\n     * Build and get the Claims Collection.\n     *\n     * @return \\Tymon\\JWTAuth\\Claims\\Collection\n     */\n    public function buildClaimsCollection()\n    {\n        return $this->buildClaims()->resolveClaims();\n    }\n\n    /**\n     * Get a Payload instance with a claims collection.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Collection  $claims\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    public function withClaims(Collection $claims)\n    {\n        return new Payload($claims, $this->validator, $this->refreshFlow);\n    }\n\n    /**\n     * Set the default claims to be added to the Payload.\n     *\n     * @param  array  $claims\n     * @return $this\n     */\n    public function setDefaultClaims(array $claims)\n    {\n        $this->defaultClaims = $claims;\n\n        return $this;\n    }\n\n    /**\n     * Helper to set the ttl.\n     *\n     * @param  int  $ttl\n     * @return $this\n     */\n    public function setTTL($ttl)\n    {\n        $this->claimFactory->setTTL($ttl);\n\n        return $this;\n    }\n\n    /**\n     * Helper to get the ttl.\n     *\n     * @return int\n     */\n    public function getTTL()\n    {\n        return $this->claimFactory->getTTL();\n    }\n\n    /**\n     * Get the default claims.\n     *\n     * @return array\n     */\n    public function getDefaultClaims()\n    {\n        return $this->defaultClaims;\n    }\n\n    /**\n     * Get the PayloadValidator instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Validators\\PayloadValidator\n     */\n    public function validator()\n    {\n        return $this->validator;\n    }\n\n    /**\n     * Magically add a claim.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return $this\n     */\n    public function __call($method, $parameters)\n    {\n        $this->addClaim($method, $parameters[0]);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/Authenticate.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Middleware;\n\nuse Closure;\n\n/** @deprecated */\nclass Authenticate extends BaseMiddleware\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException\n     */\n    public function handle($request, Closure $next)\n    {\n        $this->authenticate($request);\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/AuthenticateAndRenew.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Middleware;\n\nuse Closure;\n\n/** @deprecated */\nclass AuthenticateAndRenew extends BaseMiddleware\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException\n     */\n    public function handle($request, Closure $next)\n    {\n        $this->authenticate($request);\n\n        $response = $next($request);\n\n        // Send the refreshed token back to the client.\n        return $this->setAuthenticationHeader($response);\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/BaseMiddleware.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Middleware;\n\nuse Illuminate\\Http\\Request;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\JWTAuth;\n\n/** @deprecated */\nabstract class BaseMiddleware\n{\n    /**\n     * The JWT Authenticator.\n     *\n     * @var \\Tymon\\JWTAuth\\JWTAuth\n     */\n    protected $auth;\n\n    /**\n     * Create a new BaseMiddleware instance.\n     *\n     * @param  \\Tymon\\JWTAuth\\JWTAuth  $auth\n     * @return void\n     */\n    public function __construct(JWTAuth $auth)\n    {\n        $this->auth = $auth;\n    }\n\n    /**\n     * Check the request for the presence of a token.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return void\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException\n     */\n    public function checkForToken(Request $request)\n    {\n        if (! $this->auth->parser()->setRequest($request)->hasToken()) {\n            throw new UnauthorizedHttpException('jwt-auth', 'Token not provided');\n        }\n    }\n\n    /**\n     * Attempt to authenticate a user via the token in the request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return void\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException\n     */\n    public function authenticate(Request $request)\n    {\n        $this->checkForToken($request);\n\n        try {\n            if (! $this->auth->parseToken()->authenticate()) {\n                throw new UnauthorizedHttpException('jwt-auth', 'User not found');\n            }\n        } catch (JWTException $e) {\n            throw new UnauthorizedHttpException('jwt-auth', $e->getMessage(), $e, $e->getCode());\n        }\n    }\n\n    /**\n     * Set the authentication header.\n     *\n     * @param  \\Illuminate\\Http\\Response|\\Illuminate\\Http\\JsonResponse  $response\n     * @param  string|null  $token\n     * @return \\Illuminate\\Http\\Response|\\Illuminate\\Http\\JsonResponse\n     */\n    protected function setAuthenticationHeader($response, $token = null)\n    {\n        $token = $token ?: $this->auth->refresh();\n        $response->headers->set('Authorization', 'Bearer '.$token);\n\n        return $response;\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/Check.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Middleware;\n\nuse Closure;\nuse Exception;\n\n/** @deprecated */\nclass Check extends BaseMiddleware\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        if ($this->auth->parser()->setRequest($request)->hasToken()) {\n            try {\n                $this->auth->parseToken()->authenticate();\n            } catch (Exception $e) {\n                //\n            }\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/RefreshToken.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Middleware;\n\nuse Closure;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\n\n/** @deprecated */\nclass RefreshToken extends BaseMiddleware\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException\n     */\n    public function handle($request, Closure $next)\n    {\n        $this->checkForToken($request);\n\n        try {\n            $token = $this->auth->parseToken()->refresh();\n        } catch (JWTException $e) {\n            throw new UnauthorizedHttpException('jwt-auth', $e->getMessage(), $e, $e->getCode());\n        }\n\n        $response = $next($request);\n\n        // Send the refreshed token back to the client.\n        return $this->setAuthenticationHeader($response, $token);\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/AuthHeaders.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\nuse Tymon\\JWTAuth\\Contracts\\Http\\Parser as ParserContract;\n\nclass AuthHeaders implements ParserContract\n{\n    /**\n     * The header name.\n     *\n     * @var string\n     */\n    protected $header = 'authorization';\n\n    /**\n     * The header prefix.\n     *\n     * @var string\n     */\n    protected $prefix = 'bearer';\n\n    /**\n     * Attempt to parse the token from some other possible headers.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    protected function fromAltHeaders(Request $request)\n    {\n        return $request->server->get('HTTP_AUTHORIZATION') ?: $request->server->get('REDIRECT_HTTP_AUTHORIZATION');\n    }\n\n    /**\n     * Try to parse the token from the request header.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    public function parse(Request $request)\n    {\n        $header = $request->headers->get($this->header) ?: $this->fromAltHeaders($request);\n\n        if ($header !== null) {\n            $position = strripos($header, $this->prefix);\n\n            if ($position !== false) {\n                $header = substr($header, $position + strlen($this->prefix));\n\n                return trim(\n                    strpos($header, ',') !== false ? strstr($header, ',', true) : $header\n                );\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Set the header name.\n     *\n     * @param  string  $headerName\n     * @return $this\n     */\n    public function setHeaderName($headerName)\n    {\n        $this->header = $headerName;\n\n        return $this;\n    }\n\n    /**\n     * Set the header prefix.\n     *\n     * @param  string  $headerPrefix\n     * @return $this\n     */\n    public function setHeaderPrefix($headerPrefix)\n    {\n        $this->prefix = $headerPrefix;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/Cookies.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Crypt;\nuse Tymon\\JWTAuth\\Contracts\\Http\\Parser as ParserContract;\n\nclass Cookies implements ParserContract\n{\n    use KeyTrait;\n\n    /**\n     * Decrypt or not the cookie while parsing.\n     *\n     * @var bool\n     */\n    private $decrypt;\n\n    public function __construct($decrypt = true)\n    {\n        $this->decrypt = $decrypt;\n    }\n\n    /**\n     * Try to parse the token from the request cookies.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    public function parse(Request $request)\n    {\n        if ($this->decrypt && $request->hasCookie($this->key)) {\n            return Crypt::decrypt($request->cookie($this->key));\n        }\n\n        return $request->cookie($this->key);\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/InputSource.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\nuse Tymon\\JWTAuth\\Contracts\\Http\\Parser as ParserContract;\n\nclass InputSource implements ParserContract\n{\n    use KeyTrait;\n\n    /**\n     * Try to parse the token from the request input source.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    public function parse(Request $request)\n    {\n        return $request->input($this->key);\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/KeyTrait.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\ntrait KeyTrait\n{\n    /**\n     * The key.\n     *\n     * @var string\n     */\n    protected $key = 'token';\n\n    /**\n     * Set the key.\n     *\n     * @param  string  $key\n     * @return $this\n     */\n    public function setKey($key)\n    {\n        $this->key = $key;\n\n        return $this;\n    }\n\n    /**\n     * Get the key.\n     *\n     * @return string\n     */\n    public function getKey()\n    {\n        return $this->key;\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/LumenRouteParams.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Arr;\n\nclass LumenRouteParams extends RouteParams\n{\n    /**\n     * Try to get the token from the route parameters.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    public function parse(Request $request)\n    {\n        // WARNING: Only use this parser if you know what you're doing!\n        // It will only work with poorly-specified aspects of certain Lumen releases.\n        // Route is the expected kind of array, and has a parameter with the key we want.\n        return Arr::get($request->route(), '2.'.$this->key);\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/Parser.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\n\nclass Parser\n{\n    /**\n     * The chain.\n     *\n     * @var array\n     */\n    private $chain;\n\n    /**\n     * The request.\n     *\n     * @var \\Illuminate\\Http\\Request\n     */\n    protected $request;\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  array  $chain\n     * @return void\n     */\n    public function __construct(Request $request, array $chain = [])\n    {\n        $this->request = $request;\n        $this->chain = $chain;\n    }\n\n    /**\n     * Get the parser chain.\n     *\n     * @return array\n     */\n    public function getChain()\n    {\n        return $this->chain;\n    }\n\n    /**\n     * Add a new parser to the chain.\n     *\n     * @param  array|\\Tymon\\JWTAuth\\Contracts\\Http\\Parser  $parsers\n     * @return $this\n     */\n    public function addParser($parsers)\n    {\n        $this->chain = array_merge($this->chain, is_array($parsers) ? $parsers : [$parsers]);\n\n        return $this;\n    }\n\n    /**\n     * Set the order of the parser chain.\n     *\n     * @param  array  $chain\n     * @return $this\n     */\n    public function setChain(array $chain)\n    {\n        $this->chain = $chain;\n\n        return $this;\n    }\n\n    /**\n     * Alias for setting the order of the chain.\n     *\n     * @param  array  $chain\n     * @return $this\n     */\n    public function setChainOrder(array $chain)\n    {\n        return $this->setChain($chain);\n    }\n\n    /**\n     * Iterate through the parsers and attempt to retrieve\n     * a value, otherwise return null.\n     *\n     * @return string|null\n     */\n    public function parseToken()\n    {\n        foreach ($this->chain as $parser) {\n            if ($response = $parser->parse($this->request)) {\n                return $response;\n            }\n        }\n    }\n\n    /**\n     * Check whether a token exists in the chain.\n     *\n     * @return bool\n     */\n    public function hasToken()\n    {\n        return $this->parseToken() !== null;\n    }\n\n    /**\n     * Set the request instance.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return $this\n     */\n    public function setRequest(Request $request)\n    {\n        $this->request = $request;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/QueryString.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\nuse Tymon\\JWTAuth\\Contracts\\Http\\Parser as ParserContract;\n\nclass QueryString implements ParserContract\n{\n    use KeyTrait;\n\n    /**\n     * Try to parse the token from the request query string.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    public function parse(Request $request)\n    {\n        return $request->query($this->key);\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/RouteParams.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\nuse Tymon\\JWTAuth\\Contracts\\Http\\Parser as ParserContract;\n\nclass RouteParams implements ParserContract\n{\n    use KeyTrait;\n\n    /**\n     * Try to get the token from the route parameters.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return null|string\n     */\n    public function parse(Request $request)\n    {\n        $route = $request->route();\n\n        // Route may not be an instance of Illuminate\\Routing\\Route\n        // (it's an array in Lumen <5.2) or not exist at all\n        // (if the request was never dispatched)\n        if (is_callable([$route, 'parameter'])) {\n            return $route->parameter($this->key);\n        }\n    }\n}\n"
  },
  {
    "path": "src/JWT.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse BadMethodCallException;\nuse Illuminate\\Http\\Request;\nuse Tymon\\JWTAuth\\Contracts\\JWTSubject;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\nuse Tymon\\JWTAuth\\Support\\CustomClaims;\n\nclass JWT\n{\n    use CustomClaims;\n\n    /**\n     * The authentication manager.\n     *\n     * @var \\Tymon\\JWTAuth\\Manager\n     */\n    protected $manager;\n\n    /**\n     * The HTTP parser.\n     *\n     * @var \\Tymon\\JWTAuth\\Http\\Parser\\Parser\n     */\n    protected $parser;\n\n    /**\n     * The token.\n     *\n     * @var \\Tymon\\JWTAuth\\Token|null\n     */\n    protected $token;\n\n    /**\n     * Lock the subject.\n     *\n     * @var bool\n     */\n    protected $lockSubject = true;\n\n    /**\n     * JWT constructor.\n     *\n     * @param  \\Tymon\\JWTAuth\\Manager  $manager\n     * @param  \\Tymon\\JWTAuth\\Http\\Parser\\Parser  $parser\n     * @return void\n     */\n    public function __construct(Manager $manager, Parser $parser)\n    {\n        $this->manager = $manager;\n        $this->parser = $parser;\n    }\n\n    /**\n     * Generate a token for a given subject.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\JWTSubject  $subject\n     * @return string\n     */\n    public function fromSubject(JWTSubject $subject)\n    {\n        $payload = $this->makePayload($subject);\n\n        return $this->manager->encode($payload)->get();\n    }\n\n    /**\n     * Alias to generate a token for a given user.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\JWTSubject  $user\n     * @return string\n     */\n    public function fromUser(JWTSubject $user)\n    {\n        return $this->fromSubject($user);\n    }\n\n    /**\n     * Refresh an expired token.\n     *\n     * @param  bool  $forceForever\n     * @param  bool  $resetClaims\n     * @return string\n     */\n    public function refresh($forceForever = false, $resetClaims = false)\n    {\n        $this->requireToken();\n\n        return $this->manager->customClaims($this->getCustomClaims())\n                             ->refresh($this->token, $forceForever, $resetClaims)\n                             ->get();\n    }\n\n    /**\n     * Invalidate a token (add it to the blacklist).\n     *\n     * @param  bool  $forceForever\n     * @return $this\n     */\n    public function invalidate($forceForever = false)\n    {\n        $this->requireToken();\n\n        $this->manager->invalidate($this->token, $forceForever);\n\n        return $this;\n    }\n\n    /**\n     * Alias to get the payload, and as a result checks that\n     * the token is valid i.e. not expired or blacklisted.\n     *\n     * @return \\Tymon\\JWTAuth\\Payload\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    public function checkOrFail()\n    {\n        return $this->getPayload();\n    }\n\n    /**\n     * Check that the token is valid.\n     *\n     * @param  bool  $getPayload\n     * @return \\Tymon\\JWTAuth\\Payload|bool\n     */\n    public function check($getPayload = false)\n    {\n        try {\n            $payload = $this->checkOrFail();\n        } catch (JWTException $e) {\n            return false;\n        }\n\n        return $getPayload ? $payload : true;\n    }\n\n    /**\n     * Get the token.\n     *\n     * @return \\Tymon\\JWTAuth\\Token|null\n     */\n    public function getToken()\n    {\n        if ($this->token === null) {\n            try {\n                $this->parseToken();\n            } catch (JWTException $e) {\n                $this->token = null;\n            }\n        }\n\n        return $this->token;\n    }\n\n    /**\n     * Parse the token from the request.\n     *\n     * @return $this\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    public function parseToken()\n    {\n        if (! $token = $this->parser->parseToken()) {\n            throw new JWTException('The token could not be parsed from the request');\n        }\n\n        return $this->setToken($token);\n    }\n\n    /**\n     * Get the raw Payload instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    public function getPayload()\n    {\n        $this->requireToken();\n\n        return $this->manager->decode($this->token);\n    }\n\n    /**\n     * Alias for getPayload().\n     *\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    public function payload()\n    {\n        return $this->getPayload();\n    }\n\n    /**\n     * Convenience method to get a claim value.\n     *\n     * @param  string  $claim\n     * @return mixed\n     */\n    public function getClaim($claim)\n    {\n        return $this->payload()->get($claim);\n    }\n\n    /**\n     * Create a Payload instance.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\JWTSubject  $subject\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    public function makePayload(JWTSubject $subject)\n    {\n        return $this->factory()->customClaims($this->getClaimsArray($subject))->make();\n    }\n\n    /**\n     * Build the claims array and return it.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\JWTSubject  $subject\n     * @return array\n     */\n    protected function getClaimsArray(JWTSubject $subject)\n    {\n        return array_merge(\n            $this->getClaimsForSubject($subject),\n            $subject->getJWTCustomClaims(), // custom claims from JWTSubject method\n            $this->customClaims // custom claims from inline setter\n        );\n    }\n\n    /**\n     * Get the claims associated with a given subject.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\JWTSubject  $subject\n     * @return array\n     */\n    protected function getClaimsForSubject(JWTSubject $subject)\n    {\n        return array_merge([\n            'sub' => $subject->getJWTIdentifier(),\n        ], $this->lockSubject ? ['prv' => $this->hashSubjectModel($subject)] : []);\n    }\n\n    /**\n     * Hash the subject model and return it.\n     *\n     * @param  string|object  $model\n     * @return string\n     */\n    protected function hashSubjectModel($model)\n    {\n        return sha1(is_object($model) ? get_class($model) : $model);\n    }\n\n    /**\n     * Check if the subject model matches the one saved in the token.\n     *\n     * @param  string|object  $model\n     * @return bool\n     */\n    public function checkSubjectModel($model)\n    {\n        if (($prv = $this->payload()->get('prv')) === null) {\n            return true;\n        }\n\n        return $this->hashSubjectModel($model) === $prv;\n    }\n\n    /**\n     * Set the token.\n     *\n     * @param  \\Tymon\\JWTAuth\\Token|string  $token\n     * @return $this\n     */\n    public function setToken($token)\n    {\n        $this->token = $token instanceof Token ? $token : new Token($token);\n\n        return $this;\n    }\n\n    /**\n     * Unset the current token.\n     *\n     * @return $this\n     */\n    public function unsetToken()\n    {\n        $this->token = null;\n\n        return $this;\n    }\n\n    /**\n     * Ensure that a token is available.\n     *\n     * @return void\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    protected function requireToken()\n    {\n        if (! $this->token) {\n            throw new JWTException('A token is required');\n        }\n    }\n\n    /**\n     * Set the request instance.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return $this\n     */\n    public function setRequest(Request $request)\n    {\n        $this->parser->setRequest($request);\n\n        return $this;\n    }\n\n    /**\n     * Set whether the subject should be \"locked\".\n     *\n     * @param  bool  $lock\n     * @return $this\n     */\n    public function lockSubject($lock)\n    {\n        $this->lockSubject = $lock;\n\n        return $this;\n    }\n\n    /**\n     * Get the Manager instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Manager\n     */\n    public function manager()\n    {\n        return $this->manager;\n    }\n\n    /**\n     * Get the Parser instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Http\\Parser\\Parser\n     */\n    public function parser()\n    {\n        return $this->parser;\n    }\n\n    /**\n     * Get the Payload Factory.\n     *\n     * @return \\Tymon\\JWTAuth\\Factory\n     */\n    public function factory()\n    {\n        return $this->manager->getPayloadFactory();\n    }\n\n    /**\n     * Get the Blacklist.\n     *\n     * @return \\Tymon\\JWTAuth\\Blacklist\n     */\n    public function blacklist()\n    {\n        return $this->manager->getBlacklist();\n    }\n\n    /**\n     * Magically call the JWT Manager.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     *\n     * @throws \\BadMethodCallException\n     */\n    public function __call($method, $parameters)\n    {\n        if (method_exists($this->manager, $method)) {\n            return call_user_func_array([$this->manager, $method], $parameters);\n        }\n\n        throw new BadMethodCallException(\"Method [$method] does not exist.\");\n    }\n}\n"
  },
  {
    "path": "src/JWTAuth.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Auth;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\n\n/** @deprecated */\nclass JWTAuth extends JWT\n{\n    /**\n     * The authentication provider.\n     *\n     * @var \\Tymon\\JWTAuth\\Contracts\\Providers\\Auth\n     */\n    protected $auth;\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Tymon\\JWTAuth\\Manager  $manager\n     * @param  \\Tymon\\JWTAuth\\Contracts\\Providers\\Auth  $auth\n     * @param  \\Tymon\\JWTAuth\\Http\\Parser\\Parser  $parser\n     * @return void\n     */\n    public function __construct(Manager $manager, Auth $auth, Parser $parser)\n    {\n        parent::__construct($manager, $parser);\n        $this->auth = $auth;\n    }\n\n    /**\n     * Attempt to authenticate the user and return the token.\n     *\n     * @param  array  $credentials\n     * @return false|string\n     */\n    public function attempt(array $credentials)\n    {\n        if (! $this->auth->byCredentials($credentials)) {\n            return false;\n        }\n\n        return $this->fromUser($this->user());\n    }\n\n    /**\n     * Authenticate a user via a token.\n     *\n     * @return \\Tymon\\JWTAuth\\Contracts\\JWTSubject|false\n     */\n    public function authenticate()\n    {\n        $id = $this->getPayload()->get('sub');\n\n        if (! $this->auth->byId($id)) {\n            return false;\n        }\n\n        return $this->user();\n    }\n\n    /**\n     * Alias for authenticate().\n     *\n     * @return \\Tymon\\JWTAuth\\Contracts\\JWTSubject|false\n     */\n    public function toUser()\n    {\n        return $this->authenticate();\n    }\n\n    /**\n     * Get the authenticated user.\n     *\n     * @return \\Tymon\\JWTAuth\\Contracts\\JWTSubject\n     */\n    public function user()\n    {\n        return $this->auth->user();\n    }\n}\n"
  },
  {
    "path": "src/JWTGuard.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse BadMethodCallException;\nuse Illuminate\\Auth\\GuardHelpers;\nuse Illuminate\\Contracts\\Auth\\Guard;\nuse Illuminate\\Contracts\\Auth\\UserProvider;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Traits\\Macroable;\nuse Tymon\\JWTAuth\\Contracts\\JWTSubject;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\UserNotDefinedException;\n\nclass JWTGuard implements Guard\n{\n    use GuardHelpers, Macroable {\n        __call as macroCall;\n    }\n\n    /**\n     * The user we last attempted to retrieve.\n     *\n     * @var \\Illuminate\\Contracts\\Auth\\Authenticatable\n     */\n    protected $lastAttempted;\n\n    /**\n     * The JWT instance.\n     *\n     * @var \\Tymon\\JWTAuth\\JWT\n     */\n    protected $jwt;\n\n    /**\n     * The request instance.\n     *\n     * @var \\Illuminate\\Http\\Request\n     */\n    protected $request;\n\n    /**\n     * Instantiate the class.\n     *\n     * @param  \\Tymon\\JWTAuth\\JWT  $jwt\n     * @param  \\Illuminate\\Contracts\\Auth\\UserProvider  $provider\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return void\n     */\n    public function __construct(JWT $jwt, UserProvider $provider, Request $request)\n    {\n        $this->jwt = $jwt;\n        $this->provider = $provider;\n        $this->request = $request;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function user()\n    {\n        if ($this->user !== null) {\n            return $this->user;\n        }\n\n        if ($this->jwt->setRequest($this->request)->getToken() &&\n            ($payload = $this->jwt->check(true)) &&\n            $this->validateSubject()\n        ) {\n            return $this->user = $this->provider->retrieveById($payload['sub']);\n        }\n    }\n\n    /**\n     * Get the currently authenticated user or throws an exception.\n     *\n     * @return \\Illuminate\\Contracts\\Auth\\Authenticatable\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\UserNotDefinedException\n     */\n    public function userOrFail()\n    {\n        if (! $user = $this->user()) {\n            throw new UserNotDefinedException;\n        }\n\n        return $user;\n    }\n\n    /**\n     * Validate a user's credentials.\n     *\n     * @param  array  $credentials\n     * @return bool\n     */\n    public function validate(array $credentials = [])\n    {\n        return (bool) $this->attempt($credentials, false);\n    }\n\n    /**\n     * Attempt to authenticate the user using the given credentials and return the token.\n     *\n     * @param  array  $credentials\n     * @param  bool  $login\n     * @return bool|string\n     */\n    public function attempt(array $credentials = [], $login = true)\n    {\n        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);\n\n        if ($this->hasValidCredentials($user, $credentials)) {\n            return $login ? $this->login($user) : true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Create a token for a user.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\JWTSubject  $user\n     * @return string\n     */\n    public function login(JWTSubject $user)\n    {\n        $token = $this->jwt->fromUser($user);\n        $this->setToken($token)->setUser($user);\n\n        return $token;\n    }\n\n    /**\n     * Logout the user, thus invalidating the token.\n     *\n     * @param  bool  $forceForever\n     * @return void\n     */\n    public function logout($forceForever = false)\n    {\n        $this->requireToken()->invalidate($forceForever);\n\n        $this->user = null;\n        $this->jwt->unsetToken();\n    }\n\n    /**\n     * Refresh the token.\n     *\n     * @param  bool  $forceForever\n     * @param  bool  $resetClaims\n     * @return string\n     */\n    public function refresh($forceForever = false, $resetClaims = false)\n    {\n        return $this->requireToken()->refresh($forceForever, $resetClaims);\n    }\n\n    /**\n     * Invalidate the token.\n     *\n     * @param  bool  $forceForever\n     * @return \\Tymon\\JWTAuth\\JWT\n     */\n    public function invalidate($forceForever = false)\n    {\n        return $this->requireToken()->invalidate($forceForever);\n    }\n\n    /**\n     * Create a new token by User id.\n     *\n     * @param  mixed  $id\n     * @return string|null\n     */\n    public function tokenById($id)\n    {\n        if ($user = $this->provider->retrieveById($id)) {\n            return $this->jwt->fromUser($user);\n        }\n    }\n\n    /**\n     * Log a user into the application using their credentials.\n     *\n     * @param  array  $credentials\n     * @return bool\n     */\n    public function once(array $credentials = [])\n    {\n        if ($this->validate($credentials)) {\n            $this->setUser($this->lastAttempted);\n\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Log the given User into the application.\n     *\n     * @param  mixed  $id\n     * @return bool\n     */\n    public function onceUsingId($id)\n    {\n        if ($user = $this->provider->retrieveById($id)) {\n            $this->setUser($user);\n\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Alias for onceUsingId.\n     *\n     * @param  mixed  $id\n     * @return bool\n     */\n    public function byId($id)\n    {\n        return $this->onceUsingId($id);\n    }\n\n    /**\n     * Add any custom claims.\n     *\n     * @param  array  $claims\n     * @return $this\n     */\n    public function claims(array $claims)\n    {\n        $this->jwt->claims($claims);\n\n        return $this;\n    }\n\n    /**\n     * Get the raw Payload instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    public function getPayload()\n    {\n        return $this->requireToken()->getPayload();\n    }\n\n    /**\n     * Alias for getPayload().\n     *\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    public function payload()\n    {\n        return $this->getPayload();\n    }\n\n    /**\n     * Set the token.\n     *\n     * @param  \\Tymon\\JWTAuth\\Token|string  $token\n     * @return $this\n     */\n    public function setToken($token)\n    {\n        $this->jwt->setToken($token);\n\n        return $this;\n    }\n\n    /**\n     * Set the token ttl.\n     *\n     * @param  int  $ttl\n     * @return $this\n     */\n    public function setTTL($ttl)\n    {\n        $this->jwt->factory()->setTTL($ttl);\n\n        return $this;\n    }\n\n    /**\n     * Get the user provider used by the guard.\n     *\n     * @return \\Illuminate\\Contracts\\Auth\\UserProvider\n     */\n    public function getProvider()\n    {\n        return $this->provider;\n    }\n\n    /**\n     * Set the user provider used by the guard.\n     *\n     * @param  \\Illuminate\\Contracts\\Auth\\UserProvider  $provider\n     * @return $this\n     */\n    public function setProvider(UserProvider $provider)\n    {\n        $this->provider = $provider;\n\n        return $this;\n    }\n\n    /**\n     * Return the currently cached user.\n     *\n     * @return \\Illuminate\\Contracts\\Auth\\Authenticatable|null\n     */\n    public function getUser()\n    {\n        return $this->user;\n    }\n\n    /**\n     * Get the current request instance.\n     *\n     * @return \\Illuminate\\Http\\Request\n     */\n    public function getRequest()\n    {\n        return $this->request ?: Request::createFromGlobals();\n    }\n\n    /**\n     * Set the current request instance.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return $this\n     */\n    public function setRequest(Request $request)\n    {\n        $this->request = $request;\n\n        return $this;\n    }\n\n    /**\n     * Get the token's auth factory.\n     *\n     * @return \\Tymon\\JWTAuth\\Factory\n     */\n    public function factory()\n    {\n        return $this->jwt->factory();\n    }\n\n    /**\n     * Get the last user we attempted to authenticate.\n     *\n     * @return \\Illuminate\\Contracts\\Auth\\Authenticatable\n     */\n    public function getLastAttempted()\n    {\n        return $this->lastAttempted;\n    }\n\n    /**\n     * Determine if the user matches the credentials.\n     *\n     * @param  mixed  $user\n     * @param  array  $credentials\n     * @return bool\n     */\n    protected function hasValidCredentials($user, $credentials)\n    {\n        return $user !== null && $this->provider->validateCredentials($user, $credentials);\n    }\n\n    /**\n     * Ensure the JWTSubject matches what is in the token.\n     *\n     * @return bool\n     */\n    protected function validateSubject()\n    {\n        // If the provider doesn't have the necessary method\n        // to get the underlying model name then allow.\n        if (! method_exists($this->provider, 'getModel')) {\n            return true;\n        }\n\n        return $this->jwt->checkSubjectModel($this->provider->getModel());\n    }\n\n    /**\n     * Ensure that a token is available in the request.\n     *\n     * @return \\Tymon\\JWTAuth\\JWT\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    protected function requireToken()\n    {\n        if (! $this->jwt->setRequest($this->getRequest())->getToken()) {\n            throw new JWTException('Token could not be parsed from the request.');\n        }\n\n        return $this->jwt;\n    }\n\n    /**\n     * Magically call the JWT instance.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     *\n     * @throws \\BadMethodCallException\n     */\n    public function __call($method, $parameters)\n    {\n        if (method_exists($this->jwt, $method)) {\n            return call_user_func_array([$this->jwt, $method], $parameters);\n        }\n\n        if (static::hasMacro($method)) {\n            return $this->macroCall($method, $parameters);\n        }\n\n        throw new BadMethodCallException(\"Method [$method] does not exist.\");\n    }\n}\n"
  },
  {
    "path": "src/Manager.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse Tymon\\JWTAuth\\Contracts\\Providers\\JWT as JWTContract;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenBlacklistedException;\nuse Tymon\\JWTAuth\\Support\\CustomClaims;\nuse Tymon\\JWTAuth\\Support\\RefreshFlow;\n\nclass Manager\n{\n    use CustomClaims, RefreshFlow;\n\n    /**\n     * The provider.\n     *\n     * @var \\Tymon\\JWTAuth\\Contracts\\Providers\\JWT\n     */\n    protected $provider;\n\n    /**\n     * The blacklist.\n     *\n     * @var \\Tymon\\JWTAuth\\Blacklist\n     */\n    protected $blacklist;\n\n    /**\n     * the payload factory.\n     *\n     * @var \\Tymon\\JWTAuth\\Factory\n     */\n    protected $payloadFactory;\n\n    /**\n     * The blacklist flag.\n     *\n     * @var bool\n     */\n    protected $blacklistEnabled = true;\n\n    /**\n     * the persistent claims.\n     *\n     * @var array\n     */\n    protected $persistentClaims = [];\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Tymon\\JWTAuth\\Contracts\\Providers\\JWT  $provider\n     * @param  \\Tymon\\JWTAuth\\Blacklist  $blacklist\n     * @param  \\Tymon\\JWTAuth\\Factory  $payloadFactory\n     * @return void\n     */\n    public function __construct(JWTContract $provider, Blacklist $blacklist, Factory $payloadFactory)\n    {\n        $this->provider = $provider;\n        $this->blacklist = $blacklist;\n        $this->payloadFactory = $payloadFactory;\n    }\n\n    /**\n     * Encode a Payload and return the Token.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return \\Tymon\\JWTAuth\\Token\n     */\n    public function encode(Payload $payload)\n    {\n        $token = $this->provider->encode($payload->get());\n\n        return new Token($token);\n    }\n\n    /**\n     * Decode a Token and return the Payload.\n     *\n     * @param  \\Tymon\\JWTAuth\\Token  $token\n     * @param  bool  $checkBlacklist\n     * @return \\Tymon\\JWTAuth\\Payload\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\TokenBlacklistedException\n     */\n    public function decode(Token $token, $checkBlacklist = true)\n    {\n        $payloadArray = $this->provider->decode($token->get());\n\n        $payload = $this->payloadFactory\n                        ->setRefreshFlow($this->refreshFlow)\n                        ->customClaims($payloadArray)\n                        ->make();\n\n        if ($checkBlacklist && $this->blacklistEnabled && $this->blacklist->has($payload)) {\n            throw new TokenBlacklistedException('The token has been blacklisted');\n        }\n\n        return $payload;\n    }\n\n    /**\n     * Refresh a Token and return a new Token.\n     *\n     * @param  \\Tymon\\JWTAuth\\Token  $token\n     * @param  bool  $forceForever\n     * @param  bool  $resetClaims\n     * @return \\Tymon\\JWTAuth\\Token\n     */\n    public function refresh(Token $token, $forceForever = false, $resetClaims = false)\n    {\n        $this->setRefreshFlow();\n\n        $claims = $this->buildRefreshClaims($this->decode($token));\n\n        if ($this->blacklistEnabled) {\n            // Invalidate old token\n            $this->invalidate($token, $forceForever);\n        }\n\n        // Return the new token\n        return $this->encode(\n            $this->payloadFactory->customClaims($claims)->make($resetClaims)\n        );\n    }\n\n    /**\n     * Invalidate a Token by adding it to the blacklist.\n     *\n     * @param  \\Tymon\\JWTAuth\\Token  $token\n     * @param  bool  $forceForever\n     * @return bool\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    public function invalidate(Token $token, $forceForever = false)\n    {\n        if (! $this->blacklistEnabled) {\n            throw new JWTException('You must have the blacklist enabled to invalidate a token.');\n        }\n\n        return call_user_func(\n            [$this->blacklist, $forceForever ? 'addForever' : 'add'],\n            $this->decode($token, false)\n        );\n    }\n\n    /**\n     * Build the claims to go into the refreshed token.\n     *\n     * @param  \\Tymon\\JWTAuth\\Payload  $payload\n     * @return array\n     */\n    protected function buildRefreshClaims(Payload $payload)\n    {\n        // Get the claims to be persisted from the payload\n        $persistentClaims = collect($payload->toArray())\n            ->only($this->persistentClaims)\n            ->toArray();\n\n        // persist the relevant claims\n        return array_merge(\n            $this->customClaims,\n            $persistentClaims,\n            [\n                'sub' => $payload['sub'],\n                'iat' => $payload['iat'],\n            ]\n        );\n    }\n\n    /**\n     * Get the Payload Factory instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Factory\n     */\n    public function getPayloadFactory()\n    {\n        return $this->payloadFactory;\n    }\n\n    /**\n     * Get the JWTProvider instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Contracts\\Providers\\JWT\n     */\n    public function getJWTProvider()\n    {\n        return $this->provider;\n    }\n\n    /**\n     * Get the Blacklist instance.\n     *\n     * @return \\Tymon\\JWTAuth\\Blacklist\n     */\n    public function getBlacklist()\n    {\n        return $this->blacklist;\n    }\n\n    /**\n     * Set whether the blacklist is enabled.\n     *\n     * @param  bool  $enabled\n     * @return $this\n     */\n    public function setBlacklistEnabled($enabled)\n    {\n        $this->blacklistEnabled = $enabled;\n\n        return $this;\n    }\n\n    /**\n     * Set the claims to be persisted when refreshing a token.\n     *\n     * @param  array  $claims\n     * @return $this\n     */\n    public function setPersistentClaims(array $claims)\n    {\n        $this->persistentClaims = $claims;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Payload.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse ArrayAccess;\nuse BadMethodCallException;\nuse Countable;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Contracts\\Support\\Jsonable;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse JsonSerializable;\nuse Tymon\\JWTAuth\\Claims\\Claim;\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Exceptions\\PayloadException;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass Payload implements ArrayAccess, Arrayable, Countable, Jsonable, JsonSerializable\n{\n    /**\n     * The collection of claims.\n     *\n     * @var \\Tymon\\JWTAuth\\Claims\\Collection\n     */\n    private $claims;\n\n    /**\n     * Build the Payload.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Collection  $claims\n     * @param  \\Tymon\\JWTAuth\\Validators\\PayloadValidator  $validator\n     * @param  bool  $refreshFlow\n     * @return void\n     */\n    public function __construct(Collection $claims, PayloadValidator $validator, $refreshFlow = false)\n    {\n        $this->claims = $validator->setRefreshFlow($refreshFlow)->check($claims);\n    }\n\n    /**\n     * Get the array of claim instances.\n     *\n     * @return \\Tymon\\JWTAuth\\Claims\\Collection\n     */\n    public function getClaims()\n    {\n        return $this->claims;\n    }\n\n    /**\n     * Checks if a payload matches some expected values.\n     *\n     * @param  array  $values\n     * @param  bool  $strict\n     * @return bool\n     */\n    public function matches(array $values, $strict = false)\n    {\n        if (empty($values)) {\n            return false;\n        }\n\n        $claims = $this->getClaims();\n\n        foreach ($values as $key => $value) {\n            if (! $claims->has($key) || ! $claims->get($key)->matches($value, $strict)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Checks if a payload strictly matches some expected values.\n     *\n     * @param  array  $values\n     * @return bool\n     */\n    public function matchesStrict(array $values)\n    {\n        return $this->matches($values, true);\n    }\n\n    /**\n     * Get the payload.\n     *\n     * @param  mixed  $claim\n     * @return mixed\n     */\n    public function get($claim = null)\n    {\n        $claim = value($claim);\n\n        if ($claim !== null) {\n            if (is_array($claim)) {\n                return array_map([$this, 'get'], $claim);\n            }\n\n            return Arr::get($this->toArray(), $claim);\n        }\n\n        return $this->toArray();\n    }\n\n    /**\n     * Get the underlying Claim instance.\n     *\n     * @param  string  $claim\n     * @return \\Tymon\\JWTAuth\\Claims\\Claim\n     */\n    public function getInternal($claim)\n    {\n        return $this->claims->getByClaimName($claim);\n    }\n\n    /**\n     * Determine whether the payload has the claim (by instance).\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Claim  $claim\n     * @return bool\n     */\n    public function has(Claim $claim)\n    {\n        return $this->claims->has($claim->getName());\n    }\n\n    /**\n     * Determine whether the payload has the claim (by key).\n     *\n     * @param  string  $claim\n     * @return bool\n     */\n    public function hasKey($claim)\n    {\n        return $this->offsetExists($claim);\n    }\n\n    /**\n     * Get the array of claims.\n     *\n     * @return array\n     */\n    public function toArray()\n    {\n        return $this->claims->toPlainArray();\n    }\n\n    /**\n     * Convert the object into something JSON serializable.\n     *\n     * @return array\n     */\n    #[\\ReturnTypeWillChange]\n    public function jsonSerialize()\n    {\n        return $this->toArray();\n    }\n\n    /**\n     * Get the payload as JSON.\n     *\n     * @param  int  $options\n     * @return string\n     */\n    public function toJson($options = JSON_UNESCAPED_SLASHES)\n    {\n        return json_encode($this->toArray(), $options);\n    }\n\n    /**\n     * Get the payload as a string.\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->toJson();\n    }\n\n    /**\n     * Determine if an item exists at an offset.\n     *\n     * @param  mixed  $key\n     * @return bool\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetExists($key)\n    {\n        return Arr::has($this->toArray(), $key);\n    }\n\n    /**\n     * Get an item at a given offset.\n     *\n     * @param  mixed  $key\n     * @return mixed\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetGet($key)\n    {\n        return Arr::get($this->toArray(), $key);\n    }\n\n    /**\n     * Don't allow changing the payload as it should be immutable.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $value\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\PayloadException\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetSet($key, $value)\n    {\n        throw new PayloadException('The payload is immutable');\n    }\n\n    /**\n     * Don't allow changing the payload as it should be immutable.\n     *\n     * @param  string  $key\n     * @return void\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\PayloadException\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetUnset($key)\n    {\n        throw new PayloadException('The payload is immutable');\n    }\n\n    /**\n     * Count the number of claims.\n     *\n     * @return int\n     */\n    #[\\ReturnTypeWillChange]\n    public function count()\n    {\n        return count($this->toArray());\n    }\n\n    /**\n     * Invoke the Payload as a callable function.\n     *\n     * @param  mixed  $claim\n     * @return mixed\n     */\n    public function __invoke($claim = null)\n    {\n        return $this->get($claim);\n    }\n\n    /**\n     * Magically get a claim value.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     *\n     * @throws \\BadMethodCallException\n     */\n    public function __call($method, $parameters)\n    {\n        if (preg_match('/get(.+)\\b/i', $method, $matches)) {\n            foreach ($this->claims as $claim) {\n                if (get_class($claim) === 'Tymon\\\\JWTAuth\\\\Claims\\\\'.$matches[1]) {\n                    return $claim->getValue();\n                }\n            }\n        }\n\n        throw new BadMethodCallException(sprintf('The claim [%s] does not exist on the payload.', Str::after($method, 'get')));\n    }\n}\n"
  },
  {
    "path": "src/Providers/AbstractServiceProvider.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Namshi\\JOSE\\JWS;\nuse Tymon\\JWTAuth\\Blacklist;\nuse Tymon\\JWTAuth\\Claims\\Factory as ClaimFactory;\nuse Tymon\\JWTAuth\\Console\\JWTGenerateSecretCommand;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Auth;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\JWT as JWTContract;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Storage;\nuse Tymon\\JWTAuth\\Factory;\nuse Tymon\\JWTAuth\\Http\\Middleware\\Authenticate;\nuse Tymon\\JWTAuth\\Http\\Middleware\\AuthenticateAndRenew;\nuse Tymon\\JWTAuth\\Http\\Middleware\\Check;\nuse Tymon\\JWTAuth\\Http\\Middleware\\RefreshToken;\nuse Tymon\\JWTAuth\\Http\\Parser\\AuthHeaders;\nuse Tymon\\JWTAuth\\Http\\Parser\\InputSource;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\nuse Tymon\\JWTAuth\\Http\\Parser\\QueryString;\nuse Tymon\\JWTAuth\\JWT;\nuse Tymon\\JWTAuth\\JWTAuth;\nuse Tymon\\JWTAuth\\JWTGuard;\nuse Tymon\\JWTAuth\\Manager;\nuse Tymon\\JWTAuth\\Providers\\JWT\\Lcobucci;\nuse Tymon\\JWTAuth\\Providers\\JWT\\Namshi;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nabstract class AbstractServiceProvider extends ServiceProvider\n{\n    /**\n     * The middleware aliases.\n     *\n     * @var array\n     */\n    protected $middlewareAliases = [\n        'jwt.auth' => Authenticate::class,\n        'jwt.check' => Check::class,\n        'jwt.refresh' => RefreshToken::class,\n        'jwt.renew' => AuthenticateAndRenew::class,\n    ];\n\n    /**\n     * Boot the service provider.\n     *\n     * @return void\n     */\n    abstract public function boot();\n\n    /**\n     * Register the service provider.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->registerAliases();\n\n        $this->registerJWTProvider();\n        $this->registerAuthProvider();\n        $this->registerStorageProvider();\n        $this->registerJWTBlacklist();\n\n        $this->registerManager();\n        $this->registerTokenParser();\n\n        $this->registerJWT();\n        $this->registerJWTAuth();\n        $this->registerPayloadValidator();\n        $this->registerClaimFactory();\n        $this->registerPayloadFactory();\n        $this->registerJWTCommand();\n\n        $this->commands('tymon.jwt.secret');\n    }\n\n    /**\n     * Extend Laravel's Auth.\n     *\n     * @return void\n     */\n    protected function extendAuthGuard()\n    {\n        $this->app['auth']->extend('jwt', function ($app, $name, array $config) {\n            $guard = new JWTGuard(\n                $app['tymon.jwt'],\n                $app['auth']->createUserProvider($config['provider']),\n                $app['request']\n            );\n\n            $app->refresh('request', $guard, 'setRequest');\n\n            return $guard;\n        });\n    }\n\n    /**\n     * Bind some aliases.\n     *\n     * @return void\n     */\n    protected function registerAliases()\n    {\n        $this->app->alias('tymon.jwt', JWT::class);\n        $this->app->alias('tymon.jwt.auth', JWTAuth::class);\n        $this->app->alias('tymon.jwt.provider.jwt', JWTContract::class);\n        $this->app->alias('tymon.jwt.provider.jwt.namshi', Namshi::class);\n        $this->app->alias('tymon.jwt.provider.jwt.lcobucci', Lcobucci::class);\n        $this->app->alias('tymon.jwt.provider.auth', Auth::class);\n        $this->app->alias('tymon.jwt.provider.storage', Storage::class);\n        $this->app->alias('tymon.jwt.manager', Manager::class);\n        $this->app->alias('tymon.jwt.blacklist', Blacklist::class);\n        $this->app->alias('tymon.jwt.payload.factory', Factory::class);\n        $this->app->alias('tymon.jwt.validators.payload', PayloadValidator::class);\n    }\n\n    /**\n     * Register the bindings for the JSON Web Token provider.\n     *\n     * @return void\n     */\n    protected function registerJWTProvider()\n    {\n        $this->registerNamshiProvider();\n        $this->registerLcobucciProvider();\n\n        $this->app->singleton('tymon.jwt.provider.jwt', function ($app) {\n            return $this->getConfigInstance('providers.jwt');\n        });\n    }\n\n    /**\n     * Register the bindings for the Lcobucci JWT provider.\n     *\n     * @return void\n     */\n    protected function registerNamshiProvider()\n    {\n        $this->app->singleton('tymon.jwt.provider.jwt.namshi', function ($app) {\n            return new Namshi(\n                new JWS(['typ' => 'JWT', 'alg' => $this->config('algo')]),\n                $this->config('secret'),\n                $this->config('algo'),\n                $this->config('keys')\n            );\n        });\n    }\n\n    /**\n     * Register the bindings for the Lcobucci JWT provider.\n     *\n     * @return void\n     */\n    protected function registerLcobucciProvider()\n    {\n        $this->app->singleton('tymon.jwt.provider.jwt.lcobucci', function ($app) {\n            return new Lcobucci(\n                $this->config('secret'),\n                $this->config('algo'),\n                $this->config('keys')\n            );\n        });\n    }\n\n    /**\n     * Register the bindings for the Auth provider.\n     *\n     * @return void\n     */\n    protected function registerAuthProvider()\n    {\n        $this->app->singleton('tymon.jwt.provider.auth', function () {\n            return $this->getConfigInstance('providers.auth');\n        });\n    }\n\n    /**\n     * Register the bindings for the Storage provider.\n     *\n     * @return void\n     */\n    protected function registerStorageProvider()\n    {\n        $this->app->singleton('tymon.jwt.provider.storage', function () {\n            return $this->getConfigInstance('providers.storage');\n        });\n    }\n\n    /**\n     * Register the bindings for the JWT Manager.\n     *\n     * @return void\n     */\n    protected function registerManager()\n    {\n        $this->app->singleton('tymon.jwt.manager', function ($app) {\n            $instance = new Manager(\n                $app['tymon.jwt.provider.jwt'],\n                $app['tymon.jwt.blacklist'],\n                $app['tymon.jwt.payload.factory']\n            );\n\n            return $instance->setBlacklistEnabled((bool) $this->config('blacklist_enabled'))\n                            ->setPersistentClaims($this->config('persistent_claims'));\n        });\n    }\n\n    /**\n     * Register the bindings for the Token Parser.\n     *\n     * @return void\n     */\n    protected function registerTokenParser()\n    {\n        $this->app->singleton('tymon.jwt.parser', function ($app) {\n            $parser = new Parser(\n                $app['request'],\n                [\n                    new AuthHeaders,\n                    new QueryString,\n                    new InputSource,\n                ]\n            );\n\n            $app->refresh('request', $parser, 'setRequest');\n\n            return $parser;\n        });\n    }\n\n    /**\n     * Register the bindings for the main JWT class.\n     *\n     * @return void\n     */\n    protected function registerJWT()\n    {\n        $this->app->singleton('tymon.jwt', function ($app) {\n            return (new JWT(\n                $app['tymon.jwt.manager'],\n                $app['tymon.jwt.parser']\n            ))->lockSubject($this->config('lock_subject'));\n        });\n    }\n\n    /**\n     * Register the bindings for the main JWTAuth class.\n     *\n     * @return void\n     */\n    protected function registerJWTAuth()\n    {\n        $this->app->singleton('tymon.jwt.auth', function ($app) {\n            return (new JWTAuth(\n                $app['tymon.jwt.manager'],\n                $app['tymon.jwt.provider.auth'],\n                $app['tymon.jwt.parser']\n            ))->lockSubject($this->config('lock_subject'));\n        });\n    }\n\n    /**\n     * Register the bindings for the Blacklist.\n     *\n     * @return void\n     */\n    protected function registerJWTBlacklist()\n    {\n        $this->app->singleton('tymon.jwt.blacklist', function ($app) {\n            $instance = new Blacklist($app['tymon.jwt.provider.storage']);\n\n            return $instance->setGracePeriod($this->config('blacklist_grace_period'))\n                            ->setRefreshTTL($this->config('refresh_ttl'));\n        });\n    }\n\n    /**\n     * Register the bindings for the payload validator.\n     *\n     * @return void\n     */\n    protected function registerPayloadValidator()\n    {\n        $this->app->singleton('tymon.jwt.validators.payload', function () {\n            return (new PayloadValidator)\n                ->setRefreshTTL($this->config('refresh_ttl'))\n                ->setRequiredClaims($this->config('required_claims'));\n        });\n    }\n\n    /**\n     * Register the bindings for the Claim Factory.\n     *\n     * @return void\n     */\n    protected function registerClaimFactory()\n    {\n        $this->app->singleton('tymon.jwt.claim.factory', function ($app) {\n            $factory = new ClaimFactory($app['request']);\n            $app->refresh('request', $factory, 'setRequest');\n\n            return $factory->setTTL($this->config('ttl'))\n                           ->setLeeway($this->config('leeway'));\n        });\n    }\n\n    /**\n     * Register the bindings for the Payload Factory.\n     *\n     * @return void\n     */\n    protected function registerPayloadFactory()\n    {\n        $this->app->singleton('tymon.jwt.payload.factory', function ($app) {\n            return new Factory(\n                $app['tymon.jwt.claim.factory'],\n                $app['tymon.jwt.validators.payload']\n            );\n        });\n    }\n\n    /**\n     * Register the Artisan command.\n     *\n     * @return void\n     */\n    protected function registerJWTCommand()\n    {\n        $this->app->singleton('tymon.jwt.secret', function () {\n            return new JWTGenerateSecretCommand;\n        });\n    }\n\n    /**\n     * Helper to get the config values.\n     *\n     * @param  string  $key\n     * @param  string  $default\n     * @return mixed\n     */\n    protected function config($key, $default = null)\n    {\n        return config(\"jwt.$key\", $default);\n    }\n\n    /**\n     * Get an instantiable configuration instance.\n     *\n     * @param  string  $key\n     * @return mixed\n     */\n    protected function getConfigInstance($key)\n    {\n        $instance = $this->config($key);\n\n        if (is_string($instance)) {\n            return $this->app->make($instance);\n        }\n\n        return $instance;\n    }\n}\n"
  },
  {
    "path": "src/Providers/Auth/Illuminate.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Providers\\Auth;\n\nuse Illuminate\\Contracts\\Auth\\Guard as GuardContract;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Auth;\n\nclass Illuminate implements Auth\n{\n    /**\n     * The authentication guard.\n     *\n     * @var \\Illuminate\\Contracts\\Auth\\Guard\n     */\n    protected $auth;\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Illuminate\\Contracts\\Auth\\Guard  $auth\n     * @return void\n     */\n    public function __construct(GuardContract $auth)\n    {\n        $this->auth = $auth;\n    }\n\n    /**\n     * Check a user's credentials.\n     *\n     * @param  array  $credentials\n     * @return bool\n     */\n    public function byCredentials(array $credentials)\n    {\n        return $this->auth->once($credentials);\n    }\n\n    /**\n     * Authenticate a user via the id.\n     *\n     * @param  mixed  $id\n     * @return bool\n     */\n    public function byId($id)\n    {\n        return $this->auth->onceUsingId($id);\n    }\n\n    /**\n     * Get the currently authenticated user.\n     *\n     * @return mixed\n     */\n    public function user()\n    {\n        return $this->auth->user();\n    }\n}\n"
  },
  {
    "path": "src/Providers/JWT/Lcobucci.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Providers\\JWT;\n\nuse Composer\\InstalledVersions;\nuse DateTimeImmutable;\nuse DateTimeInterface;\nuse Exception;\nuse Illuminate\\Support\\Collection;\nuse Lcobucci\\JWT\\Configuration;\nuse Lcobucci\\JWT\\Signer;\nuse Lcobucci\\JWT\\Signer\\Ecdsa;\nuse Lcobucci\\JWT\\Signer\\Key;\nuse Lcobucci\\JWT\\Signer\\Key\\InMemory;\nuse Lcobucci\\JWT\\Signer\\Rsa;\nuse Lcobucci\\JWT\\Token\\Builder;\nuse Lcobucci\\JWT\\Token\\RegisteredClaims;\nuse Lcobucci\\JWT\\Validation\\Constraint\\SignedWith;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\JWT;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\n\nclass Lcobucci extends Provider implements JWT\n{\n    /**\n     * \\Lcobucci\\JWT\\Signer.\n     */\n    protected $signer;\n\n    /**\n     * \\Lcobucci\\JWT\\Configuration.\n     */\n    protected $config;\n\n    /**\n     * Create the Lcobucci provider.\n     *\n     * @param  string  $secret\n     * @param  string  $algo\n     * @param  array  $keys\n     * @param  \\Lcobucci\\JWT\\Configuration|null  $config\n     * @return void\n     */\n    public function __construct($secret, $algo, array $keys, $config = null)\n    {\n        parent::__construct($secret, $algo, $keys);\n\n        $this->signer = $this->getSigner();\n        $this->config = $config ?: $this->buildConfig();\n    }\n\n    /**\n     * Signers that this provider supports.\n     *\n     * @var array\n     */\n    protected $signers = [\n        self::ALGO_HS256 => Signer\\Hmac\\Sha256::class,\n        self::ALGO_HS384 => Signer\\Hmac\\Sha384::class,\n        self::ALGO_HS512 => Signer\\Hmac\\Sha512::class,\n        self::ALGO_RS256 => Signer\\Rsa\\Sha256::class,\n        self::ALGO_RS384 => Signer\\Rsa\\Sha384::class,\n        self::ALGO_RS512 => Signer\\Rsa\\Sha512::class,\n        self::ALGO_ES256 => Signer\\Ecdsa\\Sha256::class,\n        self::ALGO_ES384 => Signer\\Ecdsa\\Sha384::class,\n        self::ALGO_ES512 => Signer\\Ecdsa\\Sha512::class,\n    ];\n\n    /**\n     * Create a JSON Web Token.\n     *\n     * @param  array  $payload\n     * @return string\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    public function encode(array $payload)\n    {\n        $builder = $this->getBuilderFromClaims($payload);\n\n        try {\n            return $builder\n                ->getToken($this->config->signer(), $this->config->signingKey())\n                ->toString();\n        } catch (Exception $e) {\n            throw new JWTException('Could not create token: '.$e->getMessage(), $e->getCode(), $e);\n        }\n    }\n\n    /**\n     * Decode a JSON Web Token.\n     *\n     * @param  string  $token\n     * @return array\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    public function decode($token)\n    {\n        try {\n            /** @var \\Lcobucci\\JWT\\Token\\Plain */\n            $token = $this->config->parser()->parse($token);\n        } catch (Exception $e) {\n            throw new TokenInvalidException('Could not decode token: '.$e->getMessage(), $e->getCode(), $e);\n        }\n\n        if (! $this->config->validator()->validate($token, ...$this->config->validationConstraints())) {\n            throw new TokenInvalidException('Token Signature could not be verified.');\n        }\n\n        return Collection::wrap($token->claims()->all())\n            ->map(function ($claim) {\n                if ($claim instanceof DateTimeInterface) {\n                    return $claim->getTimestamp();\n                }\n\n                return is_object($claim) && method_exists($claim, 'getValue')\n                    ? $claim->getValue()\n                    : $claim;\n            })\n            ->toArray();\n    }\n\n    /**\n     * Create an instance of the builder with all of the claims applied.\n     *\n     * @param  array  $payload\n     * @return \\Lcobucci\\JWT\\Token\\Builder\n     */\n    protected function getBuilderFromClaims(array $payload): Builder\n    {\n        return array_reduce(\n            array_keys($payload),\n            function (Builder $builder, string $key) use ($payload): Builder {\n                $value = $payload[$key];\n\n                return match ($key) {\n                    RegisteredClaims::ID => $builder->identifiedBy($value),\n                    RegisteredClaims::EXPIRATION_TIME => $builder->expiresAt(DateTimeImmutable::createFromFormat('U', $value)),\n                    RegisteredClaims::NOT_BEFORE => $builder->canOnlyBeUsedAfter(DateTimeImmutable::createFromFormat('U', $value)),\n                    RegisteredClaims::ISSUED_AT => $builder->issuedAt(DateTimeImmutable::createFromFormat('U', $value)),\n                    RegisteredClaims::ISSUER => $builder->issuedBy($value),\n                    RegisteredClaims::AUDIENCE => $builder->permittedFor($value),\n                    RegisteredClaims::SUBJECT => $builder->relatedTo($value),\n                    default => $builder->withClaim($key, $value),\n                };\n            },\n            $this->config->builder()\n        );\n    }\n\n    /**\n     * Build the configuration.\n     *\n     * @return \\Lcobucci\\JWT\\Configuration\n     */\n    protected function buildConfig(): Configuration\n    {\n        $config = $this->isAsymmetric()\n            ? Configuration::forAsymmetricSigner(\n                $this->signer,\n                $this->getSigningKey(),\n                $this->getVerificationKey()\n            )\n            : Configuration::forSymmetricSigner($this->signer, $this->getSigningKey());\n\n        if (method_exists($config, 'withValidationConstraints')) {\n            return $config->withValidationConstraints(\n                new SignedWith($this->signer, $this->getVerificationKey())\n            );\n        }\n\n        $config->setValidationConstraints(\n            new SignedWith($this->signer, $this->getVerificationKey())\n        );\n\n        return $config;\n    }\n\n    /**\n     * Get the signer instance.\n     *\n     * @return \\Lcobucci\\JWT\\Signer\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    protected function getSigner()\n    {\n        if (! array_key_exists($this->algo, $this->signers)) {\n            throw new JWTException('The given algorithm could not be found');\n        }\n\n        $signer = $this->signers[$this->algo];\n\n        if (is_subclass_of($signer, Ecdsa::class) && $this->usingV4()) {\n            return $signer::create();\n        }\n\n        return new $signer();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function isAsymmetric()\n    {\n        return is_subclass_of($this->signer, Rsa::class)\n            || is_subclass_of($this->signer, Ecdsa::class);\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return \\Lcobucci\\JWT\\Signer\\Key\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    protected function getSigningKey()\n    {\n        if ($this->isAsymmetric()) {\n            if (! $privateKey = $this->getPrivateKey()) {\n                throw new JWTException('Private key is not set.');\n            }\n\n            return $this->getKey($privateKey, $this->getPassphrase() ?? '');\n        }\n\n        if (! $secret = $this->getSecret()) {\n            throw new JWTException('Secret is not set.');\n        }\n\n        return $this->getKey($secret);\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return \\Lcobucci\\JWT\\Signer\\Key\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    protected function getVerificationKey()\n    {\n        if ($this->isAsymmetric()) {\n            if (! $public = $this->getPublicKey()) {\n                throw new JWTException('Public key is not set.');\n            }\n\n            return $this->getKey($public);\n        }\n\n        if (! $secret = $this->getSecret()) {\n            throw new JWTException('Secret is not set.');\n        }\n\n        return $this->getKey($secret);\n    }\n\n    /**\n     * Get the signing key instance.\n     */\n    protected function getKey(string $contents, string $passphrase = ''): Key\n    {\n        return InMemory::plainText($contents, $passphrase);\n    }\n\n    /**\n     * Determine if the lcobucci/jwt package version is less than 5.0.0.\n     */\n    protected function usingV4(): bool\n    {\n        return version_compare(InstalledVersions::getPrettyVersion('lcobucci/jwt'), '5.0.0', '<');\n    }\n}\n"
  },
  {
    "path": "src/Providers/JWT/Provider.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Providers\\JWT;\n\nuse Illuminate\\Support\\Arr;\n\nabstract class Provider\n{\n    const ALGO_HS256 = 'HS256';\n    const ALGO_HS384 = 'HS384';\n    const ALGO_HS512 = 'HS512';\n    const ALGO_RS256 = 'RS256';\n    const ALGO_RS384 = 'RS384';\n    const ALGO_RS512 = 'RS512';\n    const ALGO_ES256 = 'ES256';\n    const ALGO_ES384 = 'ES384';\n    const ALGO_ES512 = 'ES512';\n\n    /**\n     * The secret.\n     *\n     * @var string\n     */\n    protected $secret;\n\n    /**\n     * The array of keys.\n     *\n     * @var array\n     */\n    protected $keys;\n\n    /**\n     * The used algorithm.\n     *\n     * @var string\n     */\n    protected $algo;\n\n    /**\n     * Constructor.\n     *\n     * @param  string  $secret\n     * @param  string  $algo\n     * @param  array  $keys\n     * @return void\n     */\n    public function __construct($secret, $algo, array $keys)\n    {\n        $this->secret = $secret;\n        $this->algo = $algo;\n        $this->keys = $keys;\n    }\n\n    /**\n     * Set the algorithm used to sign the token.\n     *\n     * @param  string  $algo\n     * @return $this\n     */\n    public function setAlgo($algo)\n    {\n        $this->algo = $algo;\n\n        return $this;\n    }\n\n    /**\n     * Get the algorithm used to sign the token.\n     *\n     * @return string\n     */\n    public function getAlgo()\n    {\n        return $this->algo;\n    }\n\n    /**\n     * Set the secret used to sign the token.\n     *\n     * @param  string  $secret\n     * @return $this\n     */\n    public function setSecret($secret)\n    {\n        $this->secret = $secret;\n\n        return $this;\n    }\n\n    /**\n     * Get the secret used to sign the token.\n     *\n     * @return string\n     */\n    public function getSecret()\n    {\n        return $this->secret;\n    }\n\n    /**\n     * Set the keys used to sign the token.\n     *\n     * @param  array  $keys\n     * @return $this\n     */\n    public function setKeys(array $keys)\n    {\n        $this->keys = $keys;\n\n        return $this;\n    }\n\n    /**\n     * Get the array of keys used to sign tokens with an asymmetric algorithm.\n     *\n     * @return array\n     */\n    public function getKeys()\n    {\n        return $this->keys;\n    }\n\n    /**\n     * Get the public key used to sign tokens with an asymmetric algorithm.\n     *\n     * @return string|null\n     */\n    public function getPublicKey()\n    {\n        return Arr::get($this->keys, 'public');\n    }\n\n    /**\n     * Get the private key used to sign tokens with an asymmetric algorithm.\n     *\n     * @return string|null\n     */\n    public function getPrivateKey()\n    {\n        return Arr::get($this->keys, 'private');\n    }\n\n    /**\n     * Get the passphrase used to sign tokens\n     * with an asymmetric algorithm.\n     *\n     * @return string|null\n     */\n    public function getPassphrase()\n    {\n        return Arr::get($this->keys, 'passphrase');\n    }\n\n    /**\n     * Get the key used to sign the tokens.\n     *\n     * @return string|null\n     */\n    protected function getSigningKey()\n    {\n        return $this->isAsymmetric() ? $this->getPrivateKey() : $this->getSecret();\n    }\n\n    /**\n     * Get the key used to verify the tokens.\n     *\n     * @return string|null\n     */\n    protected function getVerificationKey()\n    {\n        return $this->isAsymmetric() ? $this->getPublicKey() : $this->getSecret();\n    }\n\n    /**\n     * Determine if the algorithm is asymmetric, and thus requires a public/private key combo.\n     *\n     * @return bool\n     */\n    abstract protected function isAsymmetric();\n}\n"
  },
  {
    "path": "src/Providers/LaravelServiceProvider.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Providers;\n\nuse Tymon\\JWTAuth\\Http\\Parser\\Cookies;\nuse Tymon\\JWTAuth\\Http\\Parser\\RouteParams;\n\nclass LaravelServiceProvider extends AbstractServiceProvider\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function boot()\n    {\n        $path = realpath(__DIR__.'/../../config/config.php');\n\n        $this->publishes([$path => config_path('jwt.php')], 'config');\n        $this->mergeConfigFrom($path, 'jwt');\n\n        $this->aliasMiddleware();\n\n        $this->extendAuthGuard();\n\n        $this->app['tymon.jwt.parser']->addParser([\n            new RouteParams,\n            new Cookies($this->config('decrypt_cookies')),\n        ]);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function registerStorageProvider()\n    {\n        $this->app->singleton('tymon.jwt.provider.storage', function () {\n            $instance = $this->getConfigInstance('providers.storage');\n\n            if (method_exists($instance, 'setLaravelVersion')) {\n                $instance->setLaravelVersion($this->app->version());\n            }\n\n            return $instance;\n        });\n    }\n\n    /**\n     * Alias the middleware.\n     *\n     * @return void\n     */\n    protected function aliasMiddleware()\n    {\n        $router = $this->app['router'];\n\n        $method = method_exists($router, 'aliasMiddleware') ? 'aliasMiddleware' : 'middleware';\n\n        foreach ($this->middlewareAliases as $alias => $middleware) {\n            $router->$method($alias, $middleware);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Providers/LumenServiceProvider.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Providers;\n\nuse Tymon\\JWTAuth\\Http\\Parser\\LumenRouteParams;\n\nclass LumenServiceProvider extends AbstractServiceProvider\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function boot()\n    {\n        $this->app->configure('jwt');\n\n        $path = realpath(__DIR__.'/../../config/config.php');\n        $this->mergeConfigFrom($path, 'jwt');\n\n        $this->app->routeMiddleware($this->middlewareAliases);\n\n        $this->extendAuthGuard();\n\n        $this->app['tymon.jwt.parser']->addParser(new LumenRouteParams);\n    }\n}\n"
  },
  {
    "path": "src/Providers/Storage/Illuminate.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Providers\\Storage;\n\nuse BadMethodCallException;\nuse Illuminate\\Contracts\\Cache\\Repository as CacheContract;\nuse Psr\\SimpleCache\\CacheInterface as PsrCacheInterface;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Storage;\n\nclass Illuminate implements Storage\n{\n    /**\n     * The cache repository contract.\n     *\n     * @var \\Illuminate\\Contracts\\Cache\\Repository\n     */\n    protected $cache;\n\n    /**\n     * The used cache tag.\n     *\n     * @var string\n     */\n    protected $tag = 'tymon.jwt';\n\n    /**\n     * @var bool\n     */\n    protected $supportsTags;\n\n    /**\n     * @var string|null\n     */\n    protected $laravelVersion;\n\n    /**\n     * Constructor.\n     *\n     * @param  \\Illuminate\\Contracts\\Cache\\Repository  $cache\n     * @return void\n     */\n    public function __construct(CacheContract $cache)\n    {\n        $this->cache = $cache;\n    }\n\n    /**\n     * Add a new item into storage.\n     *\n     * @param  string  $key\n     * @param  mixed  $value\n     * @param  int  $minutes\n     * @return void\n     */\n    public function add($key, $value, $minutes)\n    {\n        // If the laravel version is 5.8 or higher then convert minutes to seconds.\n        if ($this->laravelVersion !== null\n            && is_int($minutes)\n            && version_compare($this->laravelVersion, '5.8', '>=')\n        ) {\n            $minutes = $minutes * 60;\n        }\n\n        $this->cache()->put($key, $value, $minutes);\n    }\n\n    /**\n     * Add a new item into storage forever.\n     *\n     * @param  string  $key\n     * @param  mixed  $value\n     * @return void\n     */\n    public function forever($key, $value)\n    {\n        $this->cache()->forever($key, $value);\n    }\n\n    /**\n     * Get an item from storage.\n     *\n     * @param  string  $key\n     * @return mixed\n     */\n    public function get($key)\n    {\n        return $this->cache()->get($key);\n    }\n\n    /**\n     * Remove an item from storage.\n     *\n     * @param  string  $key\n     * @return bool\n     */\n    public function destroy($key)\n    {\n        return $this->cache()->forget($key);\n    }\n\n    /**\n     * Remove all items associated with the tag.\n     *\n     * @return void\n     */\n    public function flush()\n    {\n        $this->cache()->flush();\n    }\n\n    /**\n     * Return the cache instance with tags attached.\n     *\n     * @return \\Illuminate\\Contracts\\Cache\\Repository\n     */\n    protected function cache()\n    {\n        if ($this->supportsTags === null) {\n            $this->determineTagSupport();\n        }\n\n        if ($this->supportsTags) {\n            return $this->cache->tags($this->tag);\n        }\n\n        return $this->cache;\n    }\n\n    /**\n     * Set the laravel version.\n     */\n    public function setLaravelVersion($version)\n    {\n        $this->laravelVersion = $version;\n\n        return $this;\n    }\n\n    /**\n     * Detect as best we can whether tags are supported with this repository & store,\n     * and save our result on the $supportsTags flag.\n     *\n     * @return void\n     */\n    protected function determineTagSupport()\n    {\n        // Laravel >= 5.1.28\n        if (method_exists($this->cache, 'tags') || $this->cache instanceof PsrCacheInterface) {\n            try {\n                // Attempt the repository tags command, which throws exceptions when unsupported\n                $this->cache->tags($this->tag);\n                $this->supportsTags = true;\n            } catch (BadMethodCallException $ex) {\n                $this->supportsTags = false;\n            }\n        } else {\n            // Laravel <= 5.1.27\n            if (method_exists($this->cache, 'getStore')) {\n                // Check for the tags function directly on the store\n                $this->supportsTags = method_exists($this->cache->getStore(), 'tags');\n            } else {\n                // Must be using custom cache repository without getStore(), and all bets are off,\n                // or we are mocking the cache contract (in testing), which will not create a getStore method\n                $this->supportsTags = false;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Support/CustomClaims.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Support;\n\ntrait CustomClaims\n{\n    /**\n     * Custom claims.\n     *\n     * @var array\n     */\n    protected $customClaims = [];\n\n    /**\n     * Set the custom claims.\n     *\n     * @param  array  $customClaims\n     * @return $this\n     */\n    public function customClaims(array $customClaims)\n    {\n        $this->customClaims = $customClaims;\n\n        return $this;\n    }\n\n    /**\n     * Alias to set the custom claims.\n     *\n     * @param  array  $customClaims\n     * @return $this\n     */\n    public function claims(array $customClaims)\n    {\n        return $this->customClaims($customClaims);\n    }\n\n    /**\n     * Get the custom claims.\n     *\n     * @return array\n     */\n    public function getCustomClaims()\n    {\n        return $this->customClaims;\n    }\n}\n"
  },
  {
    "path": "src/Support/RefreshFlow.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Support;\n\ntrait RefreshFlow\n{\n    /**\n     * The refresh flow flag.\n     *\n     * @var bool\n     */\n    protected $refreshFlow = false;\n\n    /**\n     * Set the refresh flow flag.\n     *\n     * @param  bool  $refreshFlow\n     * @return $this\n     */\n    public function setRefreshFlow($refreshFlow = true)\n    {\n        $this->refreshFlow = $refreshFlow;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Support/Utils.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Support;\n\nuse Carbon\\Carbon;\n\nclass Utils\n{\n    /**\n     * Get the Carbon instance for the current time.\n     *\n     * @return \\Carbon\\Carbon\n     */\n    public static function now()\n    {\n        return Carbon::now('UTC');\n    }\n\n    /**\n     * Get the Carbon instance for the timestamp.\n     *\n     * @param  int  $timestamp\n     * @return \\Carbon\\Carbon\n     */\n    public static function timestamp($timestamp)\n    {\n        return Carbon::createFromTimestampUTC($timestamp)->timezone('UTC');\n    }\n\n    /**\n     * Checks if a timestamp is in the past.\n     *\n     * @param  int  $timestamp\n     * @param  int  $leeway\n     * @return bool\n     */\n    public static function isPast($timestamp, $leeway = 0)\n    {\n        $timestamp = static::timestamp($timestamp);\n\n        return $leeway > 0\n            ? $timestamp->addSeconds($leeway)->isPast()\n            : $timestamp->isPast();\n    }\n\n    /**\n     * Checks if a timestamp is in the future.\n     *\n     * @param  int  $timestamp\n     * @param  int  $leeway\n     * @return bool\n     */\n    public static function isFuture($timestamp, $leeway = 0)\n    {\n        $timestamp = static::timestamp($timestamp);\n\n        return $leeway > 0\n            ? $timestamp->subSeconds($leeway)->isFuture()\n            : $timestamp->isFuture();\n    }\n}\n"
  },
  {
    "path": "src/Token.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth;\n\nuse Tymon\\JWTAuth\\Validators\\TokenValidator;\n\nclass Token\n{\n    /**\n     * @var string\n     */\n    private $value;\n\n    /**\n     * Create a new JSON Web Token.\n     *\n     * @param  string  $value\n     * @return void\n     */\n    public function __construct($value)\n    {\n        $this->value = (string) (new TokenValidator)->check($value);\n    }\n\n    /**\n     * Get the token.\n     *\n     * @return string\n     */\n    public function get()\n    {\n        return $this->value;\n    }\n\n    /**\n     * Get the token when casting to string.\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->get();\n    }\n}\n"
  },
  {
    "path": "src/Validators/PayloadValidator.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Validators;\n\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\n\nclass PayloadValidator extends Validator\n{\n    /**\n     * The required claims.\n     *\n     * @var array\n     */\n    protected $requiredClaims = [\n        'iss',\n        'iat',\n        'exp',\n        'nbf',\n        'sub',\n        'jti',\n    ];\n\n    /**\n     * The refresh TTL.\n     *\n     * @var int\n     */\n    protected $refreshTTL = 20160;\n\n    /**\n     * Run the validations on the payload array.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Collection  $value\n     * @return \\Tymon\\JWTAuth\\Claims\\Collection\n     */\n    public function check($value)\n    {\n        $this->validateStructure($value);\n\n        return $this->refreshFlow ? $this->validateRefresh($value) : $this->validatePayload($value);\n    }\n\n    /**\n     * Ensure the payload contains the required claims and\n     * the claims have the relevant type.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Collection  $claims\n     * @return void\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\TokenInvalidException\n     */\n    protected function validateStructure(Collection $claims)\n    {\n        if ($this->requiredClaims && ! $claims->hasAllClaims($this->requiredClaims)) {\n            throw new TokenInvalidException('JWT payload does not contain the required claims');\n        }\n    }\n\n    /**\n     * Validate the payload timestamps.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Collection  $claims\n     * @return \\Tymon\\JWTAuth\\Claims\\Collection\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\TokenExpiredException\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\TokenInvalidException\n     */\n    protected function validatePayload(Collection $claims)\n    {\n        return $claims->validate('payload');\n    }\n\n    /**\n     * Check the token in the refresh flow context.\n     *\n     * @param  \\Tymon\\JWTAuth\\Claims\\Collection  $claims\n     * @return \\Tymon\\JWTAuth\\Claims\\Collection\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\TokenExpiredException\n     */\n    protected function validateRefresh(Collection $claims)\n    {\n        return $this->refreshTTL === null ? $claims : $claims->validate('refresh', $this->refreshTTL);\n    }\n\n    /**\n     * Set the required claims.\n     *\n     * @param  array  $claims\n     * @return $this\n     */\n    public function setRequiredClaims(array $claims)\n    {\n        $this->requiredClaims = $claims;\n\n        return $this;\n    }\n\n    /**\n     * Set the refresh ttl.\n     *\n     * @param  int  $ttl\n     * @return $this\n     */\n    public function setRefreshTTL($ttl)\n    {\n        $this->refreshTTL = $ttl !== null ? (int) $ttl : null;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Validators/TokenValidator.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Validators;\n\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\n\nclass TokenValidator extends Validator\n{\n    /**\n     * Check the structure of the token.\n     *\n     * @param  string  $value\n     * @return string\n     */\n    public function check($value)\n    {\n        return $this->validateStructure($value);\n    }\n\n    /**\n     * @param  string  $token\n     * @return string\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\TokenInvalidException\n     */\n    protected function validateStructure($token)\n    {\n        $parts = explode('.', $token);\n\n        if (count($parts) !== 3) {\n            throw new TokenInvalidException('Wrong number of segments');\n        }\n\n        $parts = array_filter(array_map('trim', $parts));\n\n        if (count($parts) !== 3 || implode('.', $parts) !== $token) {\n            throw new TokenInvalidException('Malformed token');\n        }\n\n        return $token;\n    }\n}\n"
  },
  {
    "path": "src/Validators/Validator.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Validators;\n\nuse Tymon\\JWTAuth\\Contracts\\Validator as ValidatorContract;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Support\\RefreshFlow;\n\nabstract class Validator implements ValidatorContract\n{\n    use RefreshFlow;\n\n    /**\n     * Helper function to return a boolean.\n     *\n     * @param  array  $value\n     * @return bool\n     */\n    public function isValid($value)\n    {\n        try {\n            $this->check($value);\n        } catch (JWTException $e) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * Run the validation.\n     *\n     * @param  array  $value\n     * @return void\n     */\n    abstract public function check($value);\n}\n"
  },
  {
    "path": "tests/AbstractTestCase.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse Carbon\\Carbon;\nuse Mockery;\nuse PHPUnit\\Framework\\TestCase;\n\nabstract class AbstractTestCase extends TestCase\n{\n    /**\n     * @var int\n     */\n    protected $testNowTimestamp;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        Carbon::setTestNow($now = Carbon::now());\n        $this->testNowTimestamp = $now->getTimestamp();\n    }\n\n    public function tearDown(): void\n    {\n        Carbon::setTestNow();\n        Mockery::close();\n\n        parent::tearDown();\n    }\n}\n"
  },
  {
    "path": "tests/BlacklistTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse Mockery;\nuse Tymon\\JWTAuth\\Blacklist;\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Storage;\nuse Tymon\\JWTAuth\\Payload;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass BlacklistTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Contracts\\Providers\\Storage|\\Mockery\\MockInterface\n     */\n    protected $storage;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\Blacklist\n     */\n    protected $blacklist;\n\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Validators\\Validator\n     */\n    protected $validator;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->storage = Mockery::mock(Storage::class);\n        $this->blacklist = new Blacklist($this->storage);\n        $this->validator = Mockery::mock(PayloadValidator::class);\n    }\n\n    /** @test */\n    public function it_should_add_a_valid_token_to_the_blacklist()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $refreshTTL = 20161;\n\n        $this->storage->shouldReceive('get')\n            ->with('foo')\n            ->once()\n            ->andReturn([]);\n\n        $this->storage->shouldReceive('add')\n            ->with('foo', ['valid_until' => $this->testNowTimestamp], $refreshTTL + 1)\n            ->once();\n\n        $this->blacklist->setRefreshTTL($refreshTTL)->add($payload);\n    }\n\n    /** @test */\n    public function it_should_add_a_token_with_no_exp_to_the_blacklist_forever()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $this->storage->shouldReceive('forever')->with('foo', 'forever')->once();\n        $this->blacklist->add($payload);\n    }\n\n    /** @test */\n    public function it_should_return_true_when_adding_an_expired_token_to_the_blacklist()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp - 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator, true);\n\n        $refreshTTL = 20161;\n\n        $this->storage->shouldReceive('get')\n            ->with('foo')\n            ->once()\n            ->andReturn([]);\n\n        $this->storage->shouldReceive('add')\n            ->with('foo', ['valid_until' => $this->testNowTimestamp], $refreshTTL + 1)\n            ->once();\n\n        $this->assertTrue($this->blacklist->setRefreshTTL($refreshTTL)->add($payload));\n    }\n\n    /** @test */\n    public function it_should_return_true_early_when_adding_an_item_and_it_already_exists()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp - 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator, true);\n\n        $refreshTTL = 20161;\n\n        $this->storage->shouldReceive('get')\n            ->with('foo')\n            ->once()\n            ->andReturn(['valid_until' => $this->testNowTimestamp]);\n\n        $this->storage->shouldReceive('add')\n            ->with('foo', ['valid_until' => $this->testNowTimestamp], $refreshTTL + 1)\n            ->never();\n\n        $this->assertTrue($this->blacklist->setRefreshTTL($refreshTTL)->add($payload));\n    }\n\n    /** @test */\n    public function it_should_check_whether_a_token_has_been_blacklisted()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foobar'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn(['valid_until' => $this->testNowTimestamp]);\n\n        $this->assertTrue($this->blacklist->has($payload));\n    }\n\n    public function blacklist_provider()\n    {\n        return [\n            [null],\n            [0],\n            [''],\n            [[]],\n            [['valid_until' => strtotime('+1day')]],\n        ];\n    }\n\n    /**\n     * @test\n     *\n     * @dataProvider blacklist_provider\n     *\n     * @param  mixed  $result\n     */\n    public function it_should_check_whether_a_token_has_not_been_blacklisted($result)\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foobar'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn($result);\n        $this->assertFalse($this->blacklist->has($payload));\n    }\n\n    /** @test */\n    public function it_should_check_whether_a_token_has_been_blacklisted_forever()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foobar'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn('forever');\n\n        $this->assertTrue($this->blacklist->has($payload));\n    }\n\n    /** @test */\n    public function it_should_check_whether_a_token_has_been_blacklisted_when_the_token_is_not_blacklisted()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foobar'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn(null);\n\n        $this->assertFalse($this->blacklist->has($payload));\n    }\n\n    /** @test */\n    public function it_should_remove_a_token_from_the_blacklist()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foobar'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $this->storage->shouldReceive('destroy')->with('foobar')->andReturn(true);\n        $this->assertTrue($this->blacklist->remove($payload));\n    }\n\n    /** @test */\n    public function it_should_set_a_custom_unique_key_for_the_blacklist()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foobar'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = new Payload($collection, $this->validator);\n\n        $this->storage->shouldReceive('get')->with(1)->once()->andReturn(['valid_until' => $this->testNowTimestamp]);\n\n        $this->assertTrue($this->blacklist->setKey('sub')->has($payload));\n        $this->assertSame(1, $this->blacklist->getKey($payload));\n    }\n\n    /** @test */\n    public function it_should_empty_the_blacklist()\n    {\n        $this->storage->shouldReceive('flush');\n        $this->assertTrue($this->blacklist->clear());\n    }\n\n    /** @test */\n    public function it_should_set_and_get_the_blacklist_grace_period()\n    {\n        $this->assertInstanceOf(Blacklist::class, $this->blacklist->setGracePeriod(15));\n        $this->assertSame(15, $this->blacklist->getGracePeriod());\n    }\n\n    /** @test */\n    public function it_should_set_and_get_the_blacklist_refresh_ttl()\n    {\n        $this->assertInstanceOf(Blacklist::class, $this->blacklist->setRefreshTTL(15));\n        $this->assertSame(15, $this->blacklist->getRefreshTTL());\n    }\n}\n"
  },
  {
    "path": "tests/Claims/ClaimTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Claims;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Exceptions\\InvalidClaimException;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nclass ClaimTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Claims\\Expiration\n     */\n    protected $claim;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->claim = new Expiration($this->testNowTimestamp);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_passing_an_invalid_value()\n    {\n        $this->expectException(InvalidClaimException::class);\n        $this->expectExceptionMessage('Invalid value provided for claim [exp]');\n\n        $this->claim->setValue('foo');\n    }\n\n    /** @test */\n    public function it_should_convert_the_claim_to_an_array()\n    {\n        $this->assertSame(['exp' => $this->testNowTimestamp], $this->claim->toArray());\n    }\n\n    /** @test */\n    public function it_should_get_the_claim_as_a_string()\n    {\n        $this->assertJsonStringEqualsJsonString((string) $this->claim, $this->claim->toJson());\n    }\n\n    /** @test */\n    public function it_should_get_the_object_as_json()\n    {\n        $this->assertJsonStringEqualsJsonString(json_encode($this->claim), $this->claim->toJson());\n    }\n\n    /** @test */\n    public function it_should_implement_arrayable()\n    {\n        $this->assertInstanceOf(Arrayable::class, $this->claim);\n    }\n}\n"
  },
  {
    "path": "tests/Claims/CollectionTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Claims;\n\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nclass CollectionTest extends AbstractTestCase\n{\n    private function getCollection()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n\n        return new Collection($claims);\n    }\n\n    /** @test */\n    public function it_should_sanitize_the_claims_to_associative_array()\n    {\n        $collection = $this->getCollection();\n\n        $this->assertSame(array_keys($collection->toArray()), ['sub', 'iss', 'exp', 'nbf', 'iat', 'jti']);\n    }\n\n    /** @test */\n    public function it_should_determine_if_a_collection_contains_all_the_given_claims()\n    {\n        $collection = $this->getCollection();\n\n        $this->assertFalse($collection->hasAllClaims(['sub', 'iss', 'exp', 'nbf', 'iat', 'jti', 'abc']));\n        $this->assertFalse($collection->hasAllClaims(['foo', 'bar']));\n        $this->assertFalse($collection->hasAllClaims([]));\n\n        $this->assertTrue($collection->hasAllClaims(['sub', 'iss']));\n        $this->assertTrue($collection->hasAllClaims(['sub', 'iss', 'exp', 'nbf', 'iat', 'jti']));\n    }\n\n    /** @test */\n    public function it_should_get_a_claim_instance_by_name()\n    {\n        $collection = $this->getCollection();\n\n        $this->assertInstanceOf(Expiration::class, $collection->getByClaimName('exp'));\n        $this->assertInstanceOf(Subject::class, $collection->getByClaimName('sub'));\n    }\n}\n"
  },
  {
    "path": "tests/Claims/DatetimeClaimTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Claims;\n\nuse Carbon\\Carbon;\nuse DateInterval;\nuse DateTime;\nuse DateTimeImmutable;\nuse DateTimeInterface;\nuse Mockery;\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Payload;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass DatetimeClaimTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Validators\\PayloadValidator\n     */\n    protected $validator;\n\n    /**\n     * @var array\n     */\n    protected $claimsTimestamp;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->validator = Mockery::mock(PayloadValidator::class);\n        $this->validator->shouldReceive('setRefreshFlow->check');\n\n        $this->claimsTimestamp = [\n            'sub' => new Subject(1),\n            'iss' => new Issuer('http://example.com'),\n            'exp' => new Expiration($this->testNowTimestamp + 3600),\n            'nbf' => new NotBefore($this->testNowTimestamp),\n            'iat' => new IssuedAt($this->testNowTimestamp),\n            'jti' => new JwtId('foo'),\n        ];\n    }\n\n    /** @test */\n    public function it_should_handle_carbon_claims()\n    {\n        $testCarbon = Carbon::createFromTimestampUTC($this->testNowTimestamp);\n        $testCarbonCopy = clone $testCarbon;\n\n        $this->assertInstanceOf(Carbon::class, $testCarbon);\n        $this->assertInstanceOf(Datetime::class, $testCarbon);\n        $this->assertInstanceOf(DatetimeInterface::class, $testCarbon);\n\n        $claimsDatetime = [\n            'sub' => new Subject(1),\n            'iss' => new Issuer('http://example.com'),\n            'exp' => new Expiration($testCarbonCopy->addHour()),\n            'nbf' => new NotBefore($testCarbon),\n            'iat' => new IssuedAt($testCarbon),\n            'jti' => new JwtId('foo'),\n        ];\n\n        $payloadTimestamp = new Payload(Collection::make($this->claimsTimestamp), $this->validator);\n        $payloadDatetime = new Payload(Collection::make($claimsDatetime), $this->validator);\n\n        $this->assertEquals($payloadTimestamp, $payloadDatetime);\n    }\n\n    /** @test */\n    public function it_should_handle_datetime_claims()\n    {\n        $testDateTime = DateTime::createFromFormat('U', $this->testNowTimestamp);\n        $testDateTimeCopy = clone $testDateTime;\n\n        $this->assertInstanceOf(DateTime::class, $testDateTime);\n        $this->assertInstanceOf(DatetimeInterface::class, $testDateTime);\n\n        $claimsDatetime = [\n            'sub' => new Subject(1),\n            'iss' => new Issuer('http://example.com'),\n            'exp' => new Expiration($testDateTimeCopy->modify('+3600 seconds')),\n            'nbf' => new NotBefore($testDateTime),\n            'iat' => new IssuedAt($testDateTime),\n            'jti' => new JwtId('foo'),\n        ];\n\n        $payloadTimestamp = new Payload(Collection::make($this->claimsTimestamp), $this->validator);\n        $payloadDatetime = new Payload(Collection::make($claimsDatetime), $this->validator);\n\n        $this->assertEquals($payloadTimestamp, $payloadDatetime);\n    }\n\n    /** @test */\n    public function it_should_handle_datetime_immutable_claims()\n    {\n        $testDateTimeImmutable = DateTimeImmutable::createFromFormat('U', (string) $this->testNowTimestamp);\n\n        $this->assertInstanceOf(DateTimeImmutable::class, $testDateTimeImmutable);\n        $this->assertInstanceOf(DatetimeInterface::class, $testDateTimeImmutable);\n\n        $claimsDatetime = [\n            'sub' => new Subject(1),\n            'iss' => new Issuer('http://example.com'),\n            'exp' => new Expiration($testDateTimeImmutable->modify('+3600 seconds')),\n            'nbf' => new NotBefore($testDateTimeImmutable),\n            'iat' => new IssuedAt($testDateTimeImmutable),\n            'jti' => new JwtId('foo'),\n        ];\n\n        $payloadTimestamp = new Payload(Collection::make($this->claimsTimestamp), $this->validator);\n        $payloadDatetime = new Payload(Collection::make($claimsDatetime), $this->validator);\n\n        $this->assertEquals($payloadTimestamp, $payloadDatetime);\n    }\n\n    /** @test */\n    public function it_should_handle_datetinterval_claims()\n    {\n        $testDateInterval = new DateInterval('PT1H');\n\n        $this->assertInstanceOf(DateInterval::class, $testDateInterval);\n\n        $claimsDateInterval = [\n            'sub' => new Subject(1),\n            'iss' => new Issuer('http://example.com'),\n            'exp' => new Expiration($testDateInterval),\n            'nbf' => new NotBefore($this->testNowTimestamp),\n            'iat' => new IssuedAt($this->testNowTimestamp),\n            'jti' => new JwtId('foo'),\n        ];\n\n        $payloadTimestamp = new Payload(Collection::make($this->claimsTimestamp), $this->validator);\n        $payloadDateInterval = new Payload(Collection::make($claimsDateInterval), $this->validator);\n\n        $this->assertEquals($payloadTimestamp, $payloadDateInterval);\n    }\n}\n"
  },
  {
    "path": "tests/Claims/FactoryTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Claims;\n\nuse Illuminate\\Http\\Request;\nuse Tymon\\JWTAuth\\Claims\\Custom;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\Factory;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\nuse Tymon\\JWTAuth\\Test\\Fixtures\\Foo;\n\nclass FactoryTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Claims\\Factory\n     */\n    protected $factory;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->factory = new Factory(Request::create('/foo', 'GET'));\n    }\n\n    /** @test */\n    public function it_should_set_the_request()\n    {\n        $factory = $this->factory->setRequest(Request::create('/bar', 'GET'));\n        $this->assertInstanceOf(Factory::class, $factory);\n    }\n\n    /** @test */\n    public function it_should_set_the_ttl()\n    {\n        $this->assertInstanceOf(Factory::class, $this->factory->setTTL(30));\n        $this->assertSame(30, $this->factory->getTTL());\n        $this->assertInstanceOf(Factory::class, $this->factory->setTTL('60'));\n        $this->assertSame(60, $this->factory->getTTL());\n    }\n\n    /** @test */\n    public function it_should_set_the_leeway()\n    {\n        $this->assertInstanceOf(Factory::class, $this->factory->setLeeway(30));\n        $this->assertSame(30, $this->factory->getLeeway());\n        $this->assertInstanceOf(Factory::class, $this->factory->setLeeway('60'));\n        $this->assertSame(60, $this->factory->getLeeway());\n    }\n\n    /** @test */\n    public function it_should_get_a_defined_claim_instance_when_passing_a_name_and_value()\n    {\n        $this->assertInstanceOf(Subject::class, $this->factory->get('sub', 1));\n        $this->assertInstanceOf(Issuer::class, $this->factory->get('iss', 'http://example.com'));\n        $this->assertInstanceOf(Expiration::class, $this->factory->get('exp', $this->testNowTimestamp + 3600));\n        $this->assertInstanceOf(NotBefore::class, $this->factory->get('nbf', $this->testNowTimestamp));\n        $this->assertInstanceOf(IssuedAt::class, $this->factory->get('iat', $this->testNowTimestamp));\n        $this->assertInstanceOf(JwtId::class, $this->factory->get('jti', 'foo'));\n    }\n\n    /** @test */\n    public function it_should_get_a_custom_claim_instance_when_passing_a_non_defined_name_and_value()\n    {\n        $this->assertInstanceOf(Custom::class, $this->factory->get('foo', ['bar']));\n    }\n\n    /** @test */\n    public function it_should_make_a_claim_instance_with_a_value()\n    {\n        $iat = $this->factory->make('iat');\n        $this->assertSame($iat->getValue(), $this->testNowTimestamp);\n        $this->assertInstanceOf(IssuedAt::class, $iat);\n\n        $nbf = $this->factory->make('nbf');\n        $this->assertSame($nbf->getValue(), $this->testNowTimestamp);\n        $this->assertInstanceOf(NotBefore::class, $nbf);\n\n        $iss = $this->factory->make('iss');\n        $this->assertSame($iss->getValue(), 'http://localhost/foo');\n        $this->assertInstanceOf(Issuer::class, $iss);\n\n        $exp = $this->factory->make('exp');\n        $this->assertSame($exp->getValue(), $this->testNowTimestamp + 3600);\n        $this->assertInstanceOf(Expiration::class, $exp);\n\n        $jti = $this->factory->make('jti');\n        $this->assertInstanceOf(JwtId::class, $jti);\n    }\n\n    /** @test */\n    public function it_should_extend_claim_factory_to_add_a_custom_claim()\n    {\n        $this->factory->extend('foo', Foo::class);\n\n        $this->assertInstanceOf(Foo::class, $this->factory->get('foo', 'bar'));\n    }\n}\n"
  },
  {
    "path": "tests/Claims/IssuedAtTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Claims;\n\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Exceptions\\InvalidClaimException;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nclass IssuedAtTest extends AbstractTestCase\n{\n    /** @test */\n    public function it_should_throw_an_exception_when_passing_a_future_timestamp()\n    {\n        $this->expectException(InvalidClaimException::class);\n        $this->expectExceptionMessage('Invalid value provided for claim [iat]');\n\n        new IssuedAt($this->testNowTimestamp + 3600);\n    }\n}\n"
  },
  {
    "path": "tests/Claims/NotBeforeTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Claims;\n\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Exceptions\\InvalidClaimException;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nclass NotBeforeTest extends AbstractTestCase\n{\n    /** @test */\n    public function it_should_throw_an_exception_when_passing_an_invalid_value()\n    {\n        $this->expectException(InvalidClaimException::class);\n        $this->expectExceptionMessage('Invalid value provided for claim [nbf]');\n\n        new NotBefore('foo');\n    }\n}\n"
  },
  {
    "path": "tests/FactoryTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse Mockery;\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Custom;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\Factory as ClaimFactory;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Factory;\nuse Tymon\\JWTAuth\\Payload;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass FactoryTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Claims\\Factory\n     */\n    protected $claimFactory;\n\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Validators\\PayloadValidator\n     */\n    protected $validator;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\Factory\n     */\n    protected $factory;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->claimFactory = Mockery::mock(ClaimFactory::class);\n        $this->validator = Mockery::mock(PayloadValidator::class);\n        $this->factory = new Factory($this->claimFactory, $this->validator);\n    }\n\n    /** @test */\n    public function it_should_return_a_payload_when_passing_an_array_of_claims()\n    {\n        $expTime = $this->testNowTimestamp + 3600;\n\n        // these are added from default claims\n        $this->claimFactory->shouldReceive('make')->twice()->with('iss')->andReturn(new Issuer('/foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('exp')->andReturn(new Expiration($expTime));\n        $this->claimFactory->shouldReceive('make')->twice()->with('jti')->andReturn(new JwtId('foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('nbf')->andReturn(new NotBefore(123));\n        $this->claimFactory->shouldReceive('make')->twice()->with('iat')->andReturn(new IssuedAt(123));\n\n        // custom claims that override\n        $this->claimFactory->shouldReceive('get')->twice()->with('sub', 1)->andReturn(new Subject(1));\n        $this->claimFactory->shouldReceive('get')->twice()->with('jti', 'foo')->andReturn(new JwtId('foo'));\n        $this->claimFactory->shouldReceive('get')->twice()->with('nbf', 123)->andReturn(new NotBefore(123));\n        $this->claimFactory->shouldReceive('get')->twice()->with('iat', 123)->andReturn(new IssuedAt(123));\n\n        $this->claimFactory->shouldReceive('getTTL')->andReturn(60);\n\n        // once\n        $claims = $this->factory->customClaims([\n            'sub' => 1,\n            'jti' => 'foo',\n            'iat' => 123,\n            'nbf' => 123,\n        ])->buildClaimsCollection();\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($claims);\n\n        // twice\n        $payload = $this->factory->claims(['sub' => 1, 'jti' => 'foo', 'iat' => 123, 'nbf' => 123])->make();\n\n        $this->assertSame($payload->get('sub'), 1);\n        $this->assertSame($payload->get('iat'), 123);\n        $this->assertSame($payload['exp'], $expTime);\n        $this->assertSame($payload['jti'], 'foo');\n\n        $this->assertInstanceOf(Payload::class, $payload);\n    }\n\n    /** @test */\n    public function it_should_return_a_payload_when_chaining_claim_methods()\n    {\n        $this->claimFactory->shouldReceive('get')->twice()->with('sub', 1)->andReturn(new Subject(1));\n        $this->claimFactory->shouldReceive('get')->twice()->with('foo', 'baz')->andReturn(new Custom('foo', 'baz'));\n\n        $this->claimFactory->shouldReceive('make')->twice()->with('iss')->andReturn(new Issuer('/foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('exp')->andReturn(new Expiration($this->testNowTimestamp + 3600));\n        $this->claimFactory->shouldReceive('make')->twice()->with('iat')->andReturn(new IssuedAt($this->testNowTimestamp));\n        $this->claimFactory->shouldReceive('make')->twice()->with('jti')->andReturn(new JwtId('foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('nbf')->andReturn(new NotBefore($this->testNowTimestamp));\n\n        $this->claimFactory->shouldReceive('getTTL')->andReturn(60);\n\n        // once\n        $claims = $this->factory->sub(1)->foo('baz')->buildClaimsCollection();\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($claims);\n\n        // twice\n        $payload = $this->factory->sub(1)->foo('baz')->make();\n\n        $this->assertSame($payload['sub'], 1);\n        $this->assertSame($payload->get('jti'), 'foo');\n        $this->assertSame($payload->get('foo'), 'baz');\n\n        $this->assertInstanceOf(Payload::class, $payload);\n    }\n\n    /** @test */\n    public function it_should_return_a_payload_when_passing_miltidimensional_array_as_custom_claim_to_make_method()\n    {\n        // these are added from default claims\n        $this->claimFactory->shouldReceive('make')->twice()->with('iss')->andReturn(new Issuer('/foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('exp')->andReturn(new Expiration($this->testNowTimestamp + 3600));\n        $this->claimFactory->shouldReceive('make')->twice()->with('jti')->andReturn(new JwtId('foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('nbf')->andReturn(new NotBefore(123));\n        $this->claimFactory->shouldReceive('make')->twice()->with('iat')->andReturn(new IssuedAt(123));\n\n        // custom claims that override\n        $this->claimFactory->shouldReceive('get')->twice()->with('sub', 1)->andReturn(new Subject(1));\n        $this->claimFactory->shouldReceive('get')->twice()->with('foo', ['bar' => [0, 0, 0]])->andReturn(new Custom('foo', ['bar' => [0, 0, 0]]));\n\n        $this->claimFactory->shouldReceive('getTTL')->andReturn(60);\n\n        // once\n        $claims = $this->factory->sub(1)->foo(['bar' => [0, 0, 0]])->buildClaimsCollection();\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($claims);\n\n        // twice\n        $payload = $this->factory->sub(1)->foo(['bar' => [0, 0, 0]])->make();\n\n        $this->assertSame($payload->get('sub'), 1);\n        $this->assertSame($payload->get('jti'), 'foo');\n        $this->assertSame($payload->get('foo'), ['bar' => [0, 0, 0]]);\n        $this->assertSame($payload->get('foo.bar'), [0, 0, 0]);\n\n        $this->assertInstanceOf(Payload::class, $payload);\n    }\n\n    /** @test */\n    public function it_should_exclude_the_exp_claim_when_setting_ttl_to_null()\n    {\n        // these are added from default claims\n        $this->claimFactory->shouldReceive('make')->twice()->with('iss')->andReturn(new Issuer('/foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('jti')->andReturn(new JwtId('foo'));\n        $this->claimFactory->shouldReceive('make')->twice()->with('nbf')->andReturn(new NotBefore(123));\n        $this->claimFactory->shouldReceive('make')->twice()->with('iat')->andReturn(new IssuedAt(123));\n\n        // custom claims that override\n        $this->claimFactory->shouldReceive('get')->twice()->with('sub', 1)->andReturn(new Subject(1));\n\n        $this->claimFactory->shouldReceive('setTTL')->with(null)->andReturn($this->claimFactory);\n        $this->claimFactory->shouldReceive('getTTL')->andReturn(null);\n\n        // once\n        $claims = $this->factory->setTTL(null)->sub(1)->buildClaimsCollection();\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($claims);\n\n        // twice\n        $payload = $this->factory->setTTL(null)->sub(1)->make();\n\n        $this->assertNull($payload->get('exp'));\n\n        $this->assertInstanceOf(Payload::class, $payload);\n    }\n\n    /** @test */\n    public function it_should_exclude_claims_from_previous_payloads()\n    {\n        $validator = new PayloadValidator();\n        $factory = new Factory($this->claimFactory, $validator);\n\n        $fooClaim = new Custom('foo', 'bar');\n        $barClaim = new Custom('baz', 'qux');\n\n        $this->claimFactory->shouldReceive('getTTL')->andReturn(60);\n        $this->claimFactory->shouldReceive('get')->with('foo', 'bar')->twice()->andReturn($fooClaim);\n        $this->claimFactory->shouldReceive('get')->with('baz', 'qux')->once()->andReturn($barClaim);\n\n        $validator->setRequiredClaims([]);\n        $payload = $factory->setDefaultClaims([])\n            ->customClaims([\n                'foo' => 'bar',\n                'baz' => 'qux',\n            ])->make();\n\n        $this->assertSame($payload->get('foo'), 'bar');\n        $this->assertSame($payload->get('baz'), 'qux');\n\n        $payload = $factory->setDefaultClaims([])->customClaims(['foo' => 'bar'])->make(true);\n\n        $this->assertSame($payload->get('foo'), 'bar');\n        $this->assertFalse($payload->hasKey('baz'));\n    }\n\n    /** @test */\n    public function it_should_set_the_default_claims()\n    {\n        $this->factory->setDefaultClaims(['sub', 'iat']);\n\n        $this->assertSame($this->factory->getDefaultClaims(), ['sub', 'iat']);\n    }\n\n    /** @test */\n    public function it_should_get_payload_with_a_predefined_collection_of_claims()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        $payload = $this->factory->withClaims($collection);\n\n        $this->assertInstanceOf(Payload::class, $payload);\n        $this->assertSame($payload->get('sub'), 1);\n    }\n\n    /** @test */\n    public function it_should_get_the_validator()\n    {\n        $this->assertInstanceOf(PayloadValidator::class, $this->factory->validator());\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/Foo.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Fixtures;\n\nuse Tymon\\JWTAuth\\Claims\\Claim;\n\nclass Foo extends Claim\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $name = 'foo';\n}\n"
  },
  {
    "path": "tests/Http/ParserTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Http;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Routing\\Route;\nuse Illuminate\\Support\\Facades\\Crypt;\nuse Mockery;\nuse Tymon\\JWTAuth\\Contracts\\Http\\Parser as ParserContract;\nuse Tymon\\JWTAuth\\Http\\Parser\\AuthHeaders;\nuse Tymon\\JWTAuth\\Http\\Parser\\Cookies;\nuse Tymon\\JWTAuth\\Http\\Parser\\InputSource;\nuse Tymon\\JWTAuth\\Http\\Parser\\LumenRouteParams;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\nuse Tymon\\JWTAuth\\Http\\Parser\\QueryString;\nuse Tymon\\JWTAuth\\Http\\Parser\\RouteParams;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nclass ParserTest extends AbstractTestCase\n{\n    /** @test */\n    public function it_should_return_the_token_from_the_authorization_header()\n    {\n        $request = Request::create('foo', 'POST');\n        $request->headers->set('Authorization', 'Bearer foobar');\n\n        $parser = new Parser($request);\n\n        $parser->setChain([\n            new QueryString,\n            new InputSource,\n            new AuthHeaders,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_the_prefixed_authentication_header()\n    {\n        $request = Request::create('foo', 'POST');\n        $request->headers->set('Authorization', 'Custom foobar');\n\n        $parser = new Parser($request);\n\n        $parser->setChain([\n            new QueryString,\n            new InputSource,\n            (new AuthHeaders)->setHeaderPrefix('Custom'),\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_the_custom_authentication_header()\n    {\n        $request = Request::create('foo', 'POST');\n        $request->headers->set('custom_authorization', 'Bearer foobar');\n\n        $parser = new Parser($request);\n\n        $parser->setChain([\n            new QueryString,\n            new InputSource,\n            (new AuthHeaders)->setHeaderName('custom_authorization'),\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_the_alt_authorization_headers()\n    {\n        $request1 = Request::create('foo', 'POST');\n        $request1->server->set('HTTP_AUTHORIZATION', 'Bearer foobar');\n\n        $request2 = Request::create('foo', 'POST');\n        $request2->server->set('REDIRECT_HTTP_AUTHORIZATION', 'Bearer foobarbaz');\n\n        $parser = new Parser($request1, [\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n\n        $parser->setRequest($request2);\n        $this->assertSame($parser->parseToken(), 'foobarbaz');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_ignore_non_bearer_tokens()\n    {\n        $request = Request::create('foo', 'POST');\n        $request->headers->set('Authorization', 'Basic OnBhc3N3b3Jk');\n\n        $parser = new Parser($request);\n\n        $parser->setChain([\n            new QueryString,\n            new InputSource,\n            new AuthHeaders,\n            new RouteParams,\n        ]);\n\n        $this->assertNull($parser->parseToken());\n        $this->assertFalse($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_not_strip_trailing_hyphens_from_the_authorization_header()\n    {\n        $request = Request::create('foo', 'POST');\n        $request->headers->set('Authorization', 'Bearer foobar--');\n\n        $parser = new Parser($request);\n\n        $parser->setChain([\n            new QueryString,\n            new InputSource,\n            new AuthHeaders,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar--');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /**\n     * @test\n     *\n     * @dataProvider whitespaceProvider\n     */\n    public function it_should_handle_excess_whitespace_from_the_authorization_header($whitespace)\n    {\n        $request = Request::create('foo', 'POST');\n        $request->headers->set('Authorization', \"Bearer{$whitespace}foobar{$whitespace}\");\n\n        $parser = new Parser($request);\n\n        $parser->setChain([\n            new QueryString,\n            new InputSource,\n            new AuthHeaders,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    public function whitespaceProvider()\n    {\n        return [\n            'space' => [' '],\n            'multiple spaces' => ['    '],\n            'tab' => [\"\\t\"],\n            'multiple tabs' => [\"\\t\\t\\t\"],\n            'new line' => [\"\\n\"],\n            'multiple new lines' => [\"\\n\\n\\n\"],\n            'carriage return' => [\"\\r\"],\n            'carriage returns' => [\"\\r\\r\\r\"],\n            'mixture of whitespace' => [\"\\t \\n \\r \\t \\n\"],\n        ];\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_query_string()\n    {\n        $request = Request::create('foo', 'GET', ['token' => 'foobar']);\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_the_custom_query_string()\n    {\n        $request = Request::create('foo', 'GET', ['custom_token_key' => 'foobar']);\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            (new QueryString)->setKey('custom_token_key'),\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_the_query_string_not_the_input_source()\n    {\n        $request = Request::create('foo?token=foobar', 'POST', [], [], [], [], json_encode(['token' => 'foobarbaz']));\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_the_custom_query_string_not_the_custom_input_source()\n    {\n        $request = Request::create('foo?custom_token_key=foobar', 'POST', [], [], [], [], json_encode(['custom_token_key' => 'foobarbaz']));\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            (new QueryString)->setKey('custom_token_key'),\n            (new InputSource)->setKey('custom_token_key'),\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_input_source()\n    {\n        $request = Request::create('foo', 'POST', [], [], [], [], json_encode(['token' => 'foobar']));\n        $request->headers->set('Content-Type', 'application/json');\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_the_custom_input_source()\n    {\n        $request = Request::create('foo', 'POST', [], [], [], [], json_encode(['custom_token_key' => 'foobar']));\n        $request->headers->set('Content-Type', 'application/json');\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            (new InputSource)->setKey('custom_token_key'),\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_an_unencrypted_cookie()\n    {\n        $request = Request::create('foo', 'POST', [], ['token' => 'foobar']);\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n            new Cookies(false),\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_a_crypted_cookie()\n    {\n        Crypt::shouldReceive('encrypt')\n            ->with('foobar')\n            ->once()\n            ->andReturn('cryptedFoobar');\n\n        $request = Request::create('foo', 'POST', [], ['token' => Crypt::encrypt('foobar')]);\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n            new Cookies(true),\n        ]);\n\n        Crypt::shouldReceive('decrypt')\n            ->with('cryptedFoobar')\n            ->times(2)\n            ->andReturn('foobar');\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_route()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n        $request->setRouteResolver(function () {\n            return $this->getRouteMock('foobar');\n        });\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_the_token_from_route_with_a_custom_param()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n        $request->setRouteResolver(function () {\n            return $this->getRouteMock('foobar', 'custom_route_param');\n        });\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            (new RouteParams)->setKey('custom_route_param'),\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_ignore_routeless_requests()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n        $request->setRouteResolver(function () {\n            //\n        });\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertNull($parser->parseToken());\n        $this->assertFalse($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_ignore_lumen_request_arrays()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n        $request->setRouteResolver(function () {\n            return [false, ['uses' => 'someController'], ['token' => 'foobar']];\n        });\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertNull($parser->parseToken());\n        $this->assertFalse($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_accept_lumen_request_arrays_with_special_class()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n        $request->setRouteResolver(function () {\n            return [false, ['uses' => 'someController'], ['token' => 'foo.bar.baz']];\n        });\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new LumenRouteParams,\n        ]);\n\n        $this->assertSame($parser->parseToken(), 'foo.bar.baz');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_return_null_if_no_token_in_request()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n        $request->setRouteResolver(function () {\n            return $this->getRouteMock();\n        });\n\n        $parser = new Parser($request);\n        $parser->setChain([\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ]);\n\n        $this->assertNull($parser->parseToken());\n        $this->assertFalse($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_retrieve_the_chain()\n    {\n        $chain = [\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ];\n\n        $parser = new Parser(Mockery::mock(Request::class));\n        $parser->setChain($chain);\n\n        $this->assertSame($parser->getChain(), $chain);\n    }\n\n    /** @test */\n    public function it_should_retrieve_the_chain_with_alias()\n    {\n        $chain = [\n            new AuthHeaders,\n            new QueryString,\n            new InputSource,\n            new RouteParams,\n        ];\n\n        /* @var \\Illuminate\\Http\\Request $request */\n        $request = Mockery::mock(Request::class);\n\n        $parser = new Parser($request);\n        $parser->setChainOrder($chain);\n\n        $this->assertSame($parser->getChain(), $chain);\n    }\n\n    /** @test */\n    public function it_should_set_the_cookie_key()\n    {\n        $cookies = (new Cookies)->setKey('test');\n        $this->assertInstanceOf(Cookies::class, $cookies);\n    }\n\n    /** @test */\n    public function it_should_add_custom_parser()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n\n        $customParser = Mockery::mock(ParserContract::class);\n        $customParser->shouldReceive('parse')->with($request)->andReturn('foobar');\n\n        $parser = new Parser($request);\n        $parser->addParser($customParser);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    /** @test */\n    public function it_should_add_multiple_custom_parser()\n    {\n        $request = Request::create('foo', 'GET', ['foo' => 'bar']);\n\n        $customParser1 = Mockery::mock(ParserContract::class);\n        $customParser1->shouldReceive('parse')->with($request)->andReturn(false);\n\n        $customParser2 = Mockery::mock(ParserContract::class);\n        $customParser2->shouldReceive('parse')->with($request)->andReturn('foobar');\n\n        $parser = new Parser($request);\n        $parser->addParser([$customParser1, $customParser2]);\n\n        $this->assertSame($parser->parseToken(), 'foobar');\n        $this->assertTrue($parser->hasToken());\n    }\n\n    protected function getRouteMock($expectedParameterValue = null, $expectedParameterName = 'token')\n    {\n        return Mockery::mock(Route::class)\n            ->shouldReceive('parameter')\n            ->with($expectedParameterName)\n            ->andReturn($expectedParameterValue)\n            ->getMock();\n    }\n}\n"
  },
  {
    "path": "tests/JWTAuthTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse Illuminate\\Http\\Request;\nuse Mockery;\nuse stdClass;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\Auth;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Factory;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\nuse Tymon\\JWTAuth\\JWTAuth;\nuse Tymon\\JWTAuth\\Manager;\nuse Tymon\\JWTAuth\\Payload;\nuse Tymon\\JWTAuth\\Test\\Stubs\\UserStub;\nuse Tymon\\JWTAuth\\Token;\n\nclass JWTAuthTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Manager\n     */\n    protected $manager;\n\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Contracts\\Providers\\Auth\n     */\n    protected $auth;\n\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Http\\Parser\\Parser\n     */\n    protected $parser;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\JWTAuth\n     */\n    protected $jwtAuth;\n\n    public function setUp(): void\n    {\n        $this->manager = Mockery::mock(Manager::class);\n        $this->auth = Mockery::mock(Auth::class);\n        $this->parser = Mockery::mock(Parser::class);\n        $this->jwtAuth = new JWTAuth($this->manager, $this->auth, $this->parser);\n    }\n\n    /** @test */\n    public function it_should_return_a_token_when_passing_a_user()\n    {\n        $payloadFactory = Mockery::mock(Factory::class);\n        $payloadFactory->shouldReceive('make')->andReturn(Mockery::mock(Payload::class));\n\n        $this->manager\n             ->shouldReceive('getPayloadFactory->customClaims')\n             ->once()\n             ->with(['sub' => 1, 'prv' => sha1('Tymon\\JWTAuth\\Test\\Stubs\\UserStub'), 'foo' => 'bar', 'role' => 'admin'])\n             ->andReturn($payloadFactory);\n\n        $this->manager->shouldReceive('encode->get')->once()->andReturn('foo.bar.baz');\n\n        $token = $this->jwtAuth->fromUser(new UserStub);\n\n        $this->assertSame($token, 'foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_pass_provider_check_if_hash_matches()\n    {\n        $payloadFactory = Mockery::mock(Factory::class);\n        $payloadFactory->shouldReceive('make')->andReturn(Mockery::mock(Payload::class));\n        $payloadFactory->shouldReceive('get')\n                       ->with('prv')\n                       ->andReturn(sha1('Tymon\\JWTAuth\\Test\\Stubs\\UserStub'));\n\n        $this->manager->shouldReceive('decode')->once()->andReturn($payloadFactory);\n\n        $this->assertTrue($this->jwtAuth->setToken('foo.bar.baz')->checkSubjectModel('Tymon\\JWTAuth\\Test\\Stubs\\UserStub'));\n    }\n\n    /** @test */\n    public function it_should_pass_provider_check_if_hash_matches_when_provider_is_null()\n    {\n        $payloadFactory = Mockery::mock(Factory::class);\n        $payloadFactory->shouldReceive('make')->andReturn(Mockery::mock(Payload::class));\n        $payloadFactory->shouldReceive('get')\n                       ->with('prv')\n                       ->andReturnNull();\n\n        $this->manager->shouldReceive('decode')->once()->andReturn($payloadFactory);\n\n        $this->assertTrue($this->jwtAuth->setToken('foo.bar.baz')->checkSubjectModel('Tymon\\JWTAuth\\Test\\Stubs\\UserStub'));\n    }\n\n    /** @test */\n    public function it_should_not_pass_provider_check_if_hash_not_match()\n    {\n        $payloadFactory = Mockery::mock(Factory::class);\n        $payloadFactory->shouldReceive('make')->andReturn(Mockery::mock(Payload::class));\n        $payloadFactory->shouldReceive('get')\n                       ->with('prv')\n                       ->andReturn(sha1('Tymon\\JWTAuth\\Test\\Stubs\\UserStub1'));\n\n        $this->manager->shouldReceive('decode')->once()->andReturn($payloadFactory);\n\n        $this->assertFalse($this->jwtAuth->setToken('foo.bar.baz')->checkSubjectModel('Tymon\\JWTAuth\\Test\\Stubs\\UserStub'));\n    }\n\n    /** @test */\n    public function it_should_return_a_token_when_passing_valid_credentials_to_attempt_method()\n    {\n        $payloadFactory = Mockery::mock(Factory::class);\n        $payloadFactory->shouldReceive('make')->andReturn(Mockery::mock(Payload::class));\n\n        $this->manager\n             ->shouldReceive('getPayloadFactory->customClaims')\n             ->once()\n             ->with(['sub' => 1, 'prv' => sha1('Tymon\\JWTAuth\\Test\\Stubs\\UserStub'), 'foo' => 'bar', 'role' => 'admin'])\n             ->andReturn($payloadFactory);\n\n        $this->manager->shouldReceive('encode->get')->once()->andReturn('foo.bar.baz');\n\n        $this->auth->shouldReceive('byCredentials')->once()->andReturn(true);\n        $this->auth->shouldReceive('user')->once()->andReturn(new UserStub);\n\n        $token = $this->jwtAuth->attempt(['foo' => 'bar']);\n\n        $this->assertSame($token, 'foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_return_false_when_passing_invalid_credentials_to_attempt_method()\n    {\n        $this->manager->shouldReceive('encode->get')->never();\n        $this->auth->shouldReceive('byCredentials')->once()->andReturn(false);\n        $this->auth->shouldReceive('user')->never();\n\n        $token = $this->jwtAuth->attempt(['foo' => 'bar']);\n\n        $this->assertFalse($token);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_not_providing_a_token()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('A token is required');\n\n        $this->jwtAuth->toUser();\n    }\n\n    /** @test */\n    public function it_should_return_the_owning_user_from_a_token_containing_an_existing_user()\n    {\n        $payload = Mockery::mock(Payload::class);\n        $payload->shouldReceive('get')->once()->with('sub')->andReturn(1);\n\n        $this->manager->shouldReceive('decode')->once()->andReturn($payload);\n\n        $this->auth->shouldReceive('byId')->once()->with(1)->andReturn(true);\n        $this->auth->shouldReceive('user')->once()->andReturn((object) ['id' => 1]);\n\n        $user = $this->jwtAuth->setToken('foo.bar.baz')->customClaims(['foo' => 'bar'])->authenticate();\n\n        $this->assertSame($user->id, 1);\n    }\n\n    /** @test */\n    public function it_should_return_false_when_passing_a_token_not_containing_an_existing_user()\n    {\n        $payload = Mockery::mock(Payload::class);\n        $payload->shouldReceive('get')->once()->with('sub')->andReturn(1);\n\n        $this->manager->shouldReceive('decode')->once()->andReturn($payload);\n\n        $this->auth->shouldReceive('byId')->once()->with(1)->andReturn(false);\n        $this->auth->shouldReceive('user')->never();\n\n        $user = $this->jwtAuth->setToken('foo.bar.baz')->authenticate();\n\n        $this->assertFalse($user);\n    }\n\n    /** @test */\n    public function it_should_refresh_a_token()\n    {\n        $newToken = Mockery::mock(Token::class);\n        $newToken->shouldReceive('get')->once()->andReturn('baz.bar.foo');\n\n        $this->manager->shouldReceive('customClaims->refresh')->once()->andReturn($newToken);\n\n        $result = $this->jwtAuth->setToken('foo.bar.baz')->refresh();\n\n        $this->assertSame($result, 'baz.bar.foo');\n    }\n\n    /** @test */\n    public function it_should_invalidate_a_token()\n    {\n        $token = new Token('foo.bar.baz');\n\n        $this->manager->shouldReceive('invalidate')->once()->with($token, false)->andReturn(true);\n\n        $this->jwtAuth->setToken($token)->invalidate();\n    }\n\n    /** @test */\n    public function it_should_force_invalidate_a_token_forever()\n    {\n        $token = new Token('foo.bar.baz');\n\n        $this->manager->shouldReceive('invalidate')->once()->with($token, true)->andReturn(true);\n\n        $this->jwtAuth->setToken($token)->invalidate(true);\n    }\n\n    /** @test */\n    public function it_should_retrieve_the_token_from_the_request()\n    {\n        $this->parser->shouldReceive('parseToken')->andReturn('foo.bar.baz');\n\n        $this->assertInstanceOf(Token::class, $this->jwtAuth->parseToken()->getToken());\n        $this->assertEquals($this->jwtAuth->getToken(), 'foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_get_the_authenticated_user()\n    {\n        $manager = $this->jwtAuth->manager();\n        $this->assertInstanceOf(Manager::class, $manager);\n    }\n\n    /** @test */\n    public function it_should_return_false_if_the_token_is_invalid()\n    {\n        $this->parser->shouldReceive('parseToken')->andReturn('foo.bar.baz');\n        $this->manager->shouldReceive('decode')->once()->andThrow(new TokenInvalidException);\n\n        $this->assertFalse($this->jwtAuth->parseToken()->check());\n    }\n\n    /** @test */\n    public function it_should_return_true_if_the_token_is_valid()\n    {\n        $payload = Mockery::mock(Payload::class);\n\n        $this->parser->shouldReceive('parseToken')->andReturn('foo.bar.baz');\n        $this->manager->shouldReceive('decode')->once()->andReturn($payload);\n\n        $this->assertTrue($this->jwtAuth->parseToken()->check());\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_token_not_present_in_request()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('The token could not be parsed from the request');\n\n        $this->parser->shouldReceive('parseToken')->andReturn(false);\n\n        $this->jwtAuth->parseToken();\n    }\n\n    /** @test */\n    public function it_should_return_false_when_no_token_is_set()\n    {\n        $this->parser->shouldReceive('parseToken')->andReturn(false);\n\n        $this->assertNull($this->jwtAuth->getToken());\n    }\n\n    /** @test */\n    public function it_should_magically_call_the_manager()\n    {\n        $this->manager->shouldReceive('getBlacklist')->andReturn(new stdClass);\n\n        $blacklist = $this->jwtAuth->manager()->getBlacklist();\n\n        $this->assertInstanceOf(stdClass::class, $blacklist);\n    }\n\n    /** @test */\n    public function it_should_set_the_request()\n    {\n        $request = Request::create('/foo', 'GET', ['token' => 'some.random.token']);\n\n        $this->parser->shouldReceive('setRequest')->once()->with($request);\n        $this->parser->shouldReceive('parseToken')->andReturn('some.random.token');\n\n        $token = $this->jwtAuth->setRequest($request)->getToken();\n\n        $this->assertEquals('some.random.token', $token);\n    }\n\n    /** @test */\n    public function it_should_unset_the_token()\n    {\n        $this->parser->shouldReceive('parseToken')->andThrow(new JWTException);\n        $token = new Token('foo.bar.baz');\n        $this->jwtAuth->setToken($token);\n\n        $this->assertSame($this->jwtAuth->getToken(), $token);\n        $this->jwtAuth->unsetToken();\n        $this->assertNull($this->jwtAuth->getToken());\n    }\n\n    /** @test */\n    public function it_should_get_the_manager_instance()\n    {\n        $manager = $this->jwtAuth->manager();\n        $this->assertInstanceOf(Manager::class, $manager);\n    }\n\n    /** @test */\n    public function it_should_get_the_parser_instance()\n    {\n        $parser = $this->jwtAuth->parser();\n        $this->assertInstanceOf(Parser::class, $parser);\n    }\n\n    /** @test */\n    public function it_should_get_a_claim_value()\n    {\n        $payload = Mockery::mock(Payload::class);\n        $payload->shouldReceive('get')->once()->with('sub')->andReturn(1);\n\n        $this->manager->shouldReceive('decode')->once()->andReturn($payload);\n\n        $this->assertSame($this->jwtAuth->setToken('foo.bar.baz')->getClaim('sub'), 1);\n    }\n}\n"
  },
  {
    "path": "tests/JWTGuardTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse Illuminate\\Auth\\EloquentUserProvider;\nuse Illuminate\\Http\\Request;\nuse Mockery;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\UserNotDefinedException;\nuse Tymon\\JWTAuth\\Factory;\nuse Tymon\\JWTAuth\\JWT;\nuse Tymon\\JWTAuth\\JWTGuard;\nuse Tymon\\JWTAuth\\Payload;\nuse Tymon\\JWTAuth\\Test\\Stubs\\LaravelUserStub;\n\nclass JWTGuardTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\JWT|\\Mockery\\MockInterface\n     */\n    protected $jwt;\n\n    /**\n     * @var \\Illuminate\\Contracts\\Auth\\UserProvider|\\Mockery\\MockInterface\n     */\n    protected $provider;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\JWTGuard|\\Mockery\\MockInterface\n     */\n    protected $guard;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->jwt = Mockery::mock(JWT::class);\n        $this->provider = Mockery::mock(EloquentUserProvider::class);\n        $this->guard = new JWTGuard($this->jwt, $this->provider, Request::create('/foo', 'GET'));\n    }\n\n    /** @test */\n    public function it_should_get_the_request()\n    {\n        $this->assertInstanceOf(Request::class, $this->guard->getRequest());\n    }\n\n    /** @test */\n    public function it_should_get_the_authenticated_user_if_a_valid_token_is_provided()\n    {\n        $payload = Mockery::mock(Payload::class);\n        $payload->shouldReceive('offsetGet')->once()->with('sub')->andReturn(1);\n\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->once()->andReturn('foo.bar.baz');\n        $this->jwt->shouldReceive('check')->once()->with(true)->andReturn($payload);\n        $this->jwt->shouldReceive('checkSubjectModel')\n                  ->once()\n                  ->with('\\Tymon\\JWTAuth\\Test\\Stubs\\LaravelUserStub')\n                  ->andReturn(true);\n\n        $this->provider->shouldReceive('getModel')\n                       ->once()\n                       ->andReturn('\\Tymon\\JWTAuth\\Test\\Stubs\\LaravelUserStub');\n        $this->provider->shouldReceive('retrieveById')\n                       ->once()\n                       ->with(1)\n                       ->andReturn((object) ['id' => 1]);\n\n        $this->assertSame(1, $this->guard->user()->id);\n\n        // check that the user is stored on the object next time round\n        $this->assertSame(1, $this->guard->user()->id);\n        $this->assertTrue($this->guard->check());\n\n        // also make sure userOrFail does not fail\n        $this->assertSame(1, $this->guard->userOrFail()->id);\n    }\n\n    /** @test */\n    public function it_should_get_the_authenticated_user_if_a_valid_token_is_provided_and_not_throw_an_exception()\n    {\n        $payload = Mockery::mock(Payload::class);\n        $payload->shouldReceive('offsetGet')->once()->with('sub')->andReturn(1);\n\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->once()->andReturn('foo.bar.baz');\n        $this->jwt->shouldReceive('check')->once()->with(true)->andReturn($payload);\n        $this->jwt->shouldReceive('checkSubjectModel')\n                  ->once()\n                  ->with('\\Tymon\\JWTAuth\\Test\\Stubs\\LaravelUserStub')\n                  ->andReturn(true);\n\n        $this->provider->shouldReceive('getModel')\n                       ->once()\n                       ->andReturn('\\Tymon\\JWTAuth\\Test\\Stubs\\LaravelUserStub');\n        $this->provider->shouldReceive('retrieveById')\n             ->once()\n             ->with(1)\n             ->andReturn((object) ['id' => 1]);\n\n        $this->assertSame(1, $this->guard->userOrFail()->id);\n\n        // check that the user is stored on the object next time round\n        $this->assertSame(1, $this->guard->userOrFail()->id);\n        $this->assertTrue($this->guard->check());\n    }\n\n    /** @test */\n    public function it_should_return_null_if_an_invalid_token_is_provided()\n    {\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->twice()->andReturn('invalid.token.here');\n        $this->jwt->shouldReceive('check')->twice()->andReturn(false);\n        $this->jwt->shouldReceive('getPayload->get')->never();\n        $this->provider->shouldReceive('retrieveById')->never();\n\n        $this->assertNull($this->guard->user()); // once\n        $this->assertFalse($this->guard->check()); // twice\n    }\n\n    /** @test */\n    public function it_should_return_null_if_no_token_is_provided()\n    {\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->andReturn(false);\n        $this->jwt->shouldReceive('check')->never();\n        $this->jwt->shouldReceive('getPayload->get')->never();\n        $this->provider->shouldReceive('retrieveById')->never();\n\n        $this->assertNull($this->guard->user());\n        $this->assertFalse($this->guard->check());\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_if_an_invalid_token_is_provided()\n    {\n        $this->expectException(UserNotDefinedException::class);\n        $this->expectExceptionMessage('An error occurred');\n\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->twice()->andReturn('invalid.token.here');\n        $this->jwt->shouldReceive('check')->twice()->andReturn(false);\n        $this->jwt->shouldReceive('getPayload->get')->never();\n        $this->provider->shouldReceive('retrieveById')->never();\n\n        $this->assertFalse($this->guard->check()); // once\n        $this->guard->userOrFail(); // twice, throws the exception\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_if_no_token_is_provided()\n    {\n        $this->expectException(UserNotDefinedException::class);\n        $this->expectExceptionMessage('An error occurred');\n\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->andReturn(false);\n        $this->jwt->shouldReceive('check')->never();\n        $this->jwt->shouldReceive('getPayload->get')->never();\n        $this->provider->shouldReceive('retrieveById')->never();\n\n        $this->assertFalse($this->guard->check());\n        $this->guard->userOrFail(); // throws the exception\n    }\n\n    /** @test */\n    public function it_should_return_a_token_if_credentials_are_ok_and_user_is_found()\n    {\n        $credentials = ['foo' => 'bar', 'baz' => 'bob'];\n        $user = new LaravelUserStub;\n\n        $this->provider->shouldReceive('retrieveByCredentials')\n                       ->once()\n                       ->with($credentials)\n                       ->andReturn($user);\n\n        $this->provider->shouldReceive('validateCredentials')\n                       ->once()\n                       ->with($user, $credentials)\n                       ->andReturn(true);\n\n        $this->jwt->shouldReceive('fromUser')\n                  ->once()\n                  ->with($user)\n                  ->andReturn('foo.bar.baz');\n\n        $this->jwt->shouldReceive('setToken')\n                  ->once()\n                  ->with('foo.bar.baz')\n                  ->andReturnSelf();\n\n        $this->jwt->shouldReceive('claims')\n                  ->once()\n                  ->with(['foo' => 'bar'])\n                  ->andReturnSelf();\n\n        $token = $this->guard->claims(['foo' => 'bar'])->attempt($credentials);\n\n        $this->assertSame($this->guard->getLastAttempted(), $user);\n        $this->assertSame($token, 'foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_return_true_if_credentials_are_ok_and_user_is_found_when_choosing_not_to_login()\n    {\n        $credentials = ['foo' => 'bar', 'baz' => 'bob'];\n        $user = new LaravelUserStub;\n\n        $this->provider->shouldReceive('retrieveByCredentials')\n                       ->twice()\n                       ->with($credentials)\n                       ->andReturn($user);\n\n        $this->provider->shouldReceive('validateCredentials')\n                       ->twice()\n                       ->with($user, $credentials)\n                       ->andReturn(true);\n\n        $this->assertTrue($this->guard->attempt($credentials, false)); // once\n        $this->assertTrue($this->guard->validate($credentials)); // twice\n    }\n\n    /** @test */\n    public function it_should_return_false_if_credentials_are_invalid()\n    {\n        $credentials = ['foo' => 'bar', 'baz' => 'bob'];\n        $user = new LaravelUserStub;\n\n        $this->provider->shouldReceive('retrieveByCredentials')\n                       ->once()\n                       ->with($credentials)\n                       ->andReturn($user);\n\n        $this->provider->shouldReceive('validateCredentials')\n                       ->once()\n                       ->with($user, $credentials)\n                       ->andReturn(false);\n\n        $this->assertFalse($this->guard->attempt($credentials));\n    }\n\n    /** @test */\n    public function it_should_magically_call_the_jwt_instance()\n    {\n        $this->jwt->shouldReceive('factory')->andReturn(Mockery::mock(Factory::class));\n        $this->assertInstanceOf(Factory::class, $this->guard->factory());\n    }\n\n    /** @test */\n    public function it_should_logout_the_user_by_invalidating_the_token()\n    {\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->once()->andReturn(true);\n        $this->jwt->shouldReceive('invalidate')->once()->andReturn(true);\n        $this->jwt->shouldReceive('unsetToken')->once();\n\n        $this->guard->logout();\n        $this->assertNull($this->guard->getUser());\n    }\n\n    /** @test */\n    public function it_should_refresh_the_token()\n    {\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->once()->andReturn(true);\n        $this->jwt->shouldReceive('refresh')->once()->andReturn('foo.bar.baz');\n\n        $this->assertSame($this->guard->refresh(), 'foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_invalidate_the_token()\n    {\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->once()->andReturn(true);\n        $this->jwt->shouldReceive('invalidate')->once()->andReturn(true);\n\n        $this->assertTrue($this->guard->invalidate());\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_if_there_is_no_token_present_when_required()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('Token could not be parsed from the request.');\n\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->once()->andReturn(false);\n        $this->jwt->shouldReceive('refresh')->never();\n\n        $this->guard->refresh();\n    }\n\n    /** @test */\n    public function it_should_generate_a_token_by_id()\n    {\n        $user = new LaravelUserStub;\n\n        $this->provider->shouldReceive('retrieveById')\n                       ->once()\n                       ->with(1)\n                       ->andReturn($user);\n\n        $this->jwt->shouldReceive('fromUser')\n                  ->once()\n                  ->with($user)\n                  ->andReturn('foo.bar.baz');\n\n        $this->assertSame('foo.bar.baz', $this->guard->tokenById(1));\n    }\n\n    /** @test */\n    public function it_should_not_generate_a_token_by_id()\n    {\n        $this->provider->shouldReceive('retrieveById')\n                       ->once()\n                       ->with(1)\n                       ->andReturn(null);\n\n        $this->assertNull($this->guard->tokenById(1));\n    }\n\n    /** @test */\n    public function it_should_authenticate_the_user_by_credentials_and_return_true_if_valid()\n    {\n        $credentials = ['foo' => 'bar', 'baz' => 'bob'];\n        $user = new LaravelUserStub;\n\n        $this->provider->shouldReceive('retrieveByCredentials')\n                       ->once()\n                       ->with($credentials)\n                       ->andReturn($user);\n\n        $this->provider->shouldReceive('validateCredentials')\n                       ->once()\n                       ->with($user, $credentials)\n                       ->andReturn(true);\n\n        $this->assertTrue($this->guard->once($credentials));\n    }\n\n    /** @test */\n    public function it_should_attempt_to_authenticate_the_user_by_credentials_and_return_false_if_invalid()\n    {\n        $credentials = ['foo' => 'bar', 'baz' => 'bob'];\n        $user = new LaravelUserStub;\n\n        $this->provider->shouldReceive('retrieveByCredentials')\n                       ->once()\n                       ->with($credentials)\n                       ->andReturn($user);\n\n        $this->provider->shouldReceive('validateCredentials')\n                       ->once()\n                       ->with($user, $credentials)\n                       ->andReturn(false);\n\n        $this->assertFalse($this->guard->once($credentials));\n    }\n\n    /** @test */\n    public function it_should_authenticate_the_user_by_id_and_return_boolean()\n    {\n        $user = new LaravelUserStub;\n\n        $this->provider->shouldReceive('retrieveById')\n                       ->twice()\n                       ->with(1)\n                       ->andReturn($user);\n\n        $this->assertTrue($this->guard->onceUsingId(1)); // once\n        $this->assertTrue($this->guard->byId(1)); // twice\n    }\n\n    /** @test */\n    public function it_should_not_authenticate_the_user_by_id_and_return_false()\n    {\n        $this->provider->shouldReceive('retrieveById')\n                       ->twice()\n                       ->with(1)\n                       ->andReturn(null);\n\n        $this->assertFalse($this->guard->onceUsingId(1)); // once\n        $this->assertFalse($this->guard->byId(1)); // twice\n    }\n\n    /** @test */\n    public function it_should_create_a_token_from_a_user_object()\n    {\n        $user = new LaravelUserStub;\n\n        $this->jwt->shouldReceive('fromUser')\n                  ->once()\n                  ->with($user)\n                  ->andReturn('foo.bar.baz');\n\n        $this->jwt->shouldReceive('setToken')\n                  ->once()\n                  ->with('foo.bar.baz')\n                  ->andReturnSelf();\n\n        $token = $this->guard->login($user);\n\n        $this->assertSame('foo.bar.baz', $token);\n    }\n\n    /** @test */\n    public function it_should_get_the_payload()\n    {\n        $this->jwt->shouldReceive('setRequest')->andReturn($this->jwt);\n        $this->jwt->shouldReceive('getToken')->once()->andReturn('foo.bar.baz');\n        $this->jwt->shouldReceive('getPayload')->once()->andReturn(Mockery::mock(Payload::class));\n        $this->assertInstanceOf(Payload::class, $this->guard->payload());\n    }\n\n    /** @test */\n    public function it_should_be_macroable()\n    {\n        $this->guard->macro('foo', function () {\n            return 'bar';\n        });\n\n        $this->assertEquals('bar', $this->guard->foo());\n    }\n}\n"
  },
  {
    "path": "tests/ManagerTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse Mockery;\nuse Tymon\\JWTAuth\\Blacklist;\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Contracts\\Providers\\JWT;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenBlacklistedException;\nuse Tymon\\JWTAuth\\Factory;\nuse Tymon\\JWTAuth\\Manager;\nuse Tymon\\JWTAuth\\Payload;\nuse Tymon\\JWTAuth\\Token;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass ManagerTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Contracts\\Providers\\JWT\n     */\n    protected $jwt;\n\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Blacklist\n     */\n    protected $blacklist;\n\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Factory\n     */\n    protected $factory;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\Manager\n     */\n    protected $manager;\n\n    /**\n     * @var \\Mockery\\MockInterface\n     */\n    protected $validator;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->jwt = Mockery::mock(JWT::class);\n        $this->blacklist = Mockery::mock(Blacklist::class);\n        $this->factory = Mockery::mock(Factory::class);\n        $this->manager = new Manager($this->jwt, $this->blacklist, $this->factory);\n        $this->validator = Mockery::mock(PayloadValidator::class);\n    }\n\n    /** @test */\n    public function it_should_encode_a_payload()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n        $payload = new Payload($collection, $this->validator);\n\n        $this->jwt->shouldReceive('encode')->with($payload->toArray())->andReturn('foo.bar.baz');\n\n        $token = $this->manager->encode($payload);\n\n        $this->assertEquals($token, 'foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_decode_a_token()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n        $payload = new Payload($collection, $this->validator);\n\n        $token = new Token('foo.bar.baz');\n\n        $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());\n\n        $this->factory->shouldReceive('setRefreshFlow')->andReturn($this->factory);\n        $this->factory->shouldReceive('customClaims')->andReturn($this->factory);\n        $this->factory->shouldReceive('make')->andReturn($payload);\n\n        $this->blacklist->shouldReceive('has')->with($payload)->andReturn(false);\n\n        $payload = $this->manager->decode($token);\n\n        $this->assertInstanceOf(Payload::class, $payload);\n        $this->assertSame($payload->count(), 6);\n    }\n\n    /** @test */\n    public function it_should_throw_exception_when_token_is_blacklisted()\n    {\n        $this->expectException(TokenBlacklistedException::class);\n        $this->expectExceptionMessage('The token has been blacklisted');\n\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n        $payload = new Payload($collection, $this->validator);\n        $token = new Token('foo.bar.baz');\n\n        $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());\n\n        $this->factory->shouldReceive('setRefreshFlow')->andReturn($this->factory);\n        $this->factory->shouldReceive('customClaims')->with($payload->toArray())->andReturn($this->factory);\n        $this->factory->shouldReceive('make')->andReturn($payload);\n\n        $this->blacklist->shouldReceive('has')->with($payload)->andReturn(true);\n\n        $this->manager->decode($token);\n    }\n\n    /** @test */\n    public function it_should_refresh_a_token()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp - 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n        $payload = new Payload($collection, $this->validator);\n        $token = new Token('foo.bar.baz');\n\n        $this->jwt->shouldReceive('decode')->twice()->with('foo.bar.baz')->andReturn($payload->toArray());\n        $this->jwt->shouldReceive('encode')->with($payload->toArray())->andReturn('baz.bar.foo');\n\n        $this->factory->shouldReceive('setRefreshFlow')->with(true)->andReturn($this->factory);\n        $this->factory->shouldReceive('customClaims')->andReturn($this->factory);\n        $this->factory->shouldReceive('make')->andReturn($payload);\n\n        $this->blacklist->shouldReceive('has')->with($payload)->andReturn(false);\n        $this->blacklist->shouldReceive('add')->once()->with($payload);\n\n        $token = $this->manager->refresh($token);\n\n        // $this->assertArrayHasKey('ref', $payload);\n        $this->assertInstanceOf(Token::class, $token);\n        $this->assertEquals('baz.bar.foo', $token);\n    }\n\n    /** @test */\n    public function it_should_invalidate_a_token()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n        $payload = new Payload($collection, $this->validator);\n        $token = new Token('foo.bar.baz');\n\n        $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());\n\n        $this->factory->shouldReceive('setRefreshFlow')->andReturn($this->factory);\n        $this->factory->shouldReceive('customClaims')->with($payload->toArray())->andReturn($this->factory);\n        $this->factory->shouldReceive('make')->andReturn($payload);\n\n        $this->blacklist->shouldReceive('has')->with($payload)->andReturn(false);\n\n        $this->blacklist->shouldReceive('add')->with($payload)->andReturn(true);\n\n        $this->manager->invalidate($token);\n    }\n\n    /** @test */\n    public function it_should_force_invalidate_a_token_forever()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n        $collection = Collection::make($claims);\n\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n        $payload = new Payload($collection, $this->validator);\n        $token = new Token('foo.bar.baz');\n\n        $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());\n\n        $this->factory->shouldReceive('setRefreshFlow')->andReturn($this->factory);\n        $this->factory->shouldReceive('customClaims')->with($payload->toArray())->andReturn($this->factory);\n        $this->factory->shouldReceive('make')->andReturn($payload);\n\n        $this->blacklist->shouldReceive('has')->with($payload)->andReturn(false);\n\n        $this->blacklist->shouldReceive('addForever')->with($payload)->andReturn(true);\n\n        $this->manager->invalidate($token, true);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_enable_blacklist_is_set_to_false()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('You must have the blacklist enabled to invalidate a token.');\n\n        $token = new Token('foo.bar.baz');\n\n        $this->manager->setBlacklistEnabled(false)->invalidate($token);\n    }\n\n    /** @test */\n    public function it_should_get_the_payload_factory()\n    {\n        $this->assertInstanceOf(Factory::class, $this->manager->getPayloadFactory());\n    }\n\n    /** @test */\n    public function it_should_get_the_jwt_provider()\n    {\n        $this->assertInstanceOf(JWT::class, $this->manager->getJWTProvider());\n    }\n\n    /** @test */\n    public function it_should_get_the_blacklist()\n    {\n        $this->assertInstanceOf(Blacklist::class, $this->manager->getBlacklist());\n    }\n}\n"
  },
  {
    "path": "tests/Middleware/AbstractMiddlewareTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Middleware;\n\nuse Illuminate\\Http\\Request;\nuse Mockery;\nuse Tymon\\JWTAuth\\JWTAuth;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nabstract class AbstractMiddlewareTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\JWTAuth\n     */\n    protected $auth;\n\n    /**\n     * @var \\Mockery\\MockInterface|\\Illuminate\\Http\\Request\n     */\n    protected $request;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->auth = Mockery::mock(JWTAuth::class);\n        $this->request = Mockery::mock(Request::class);\n    }\n}\n"
  },
  {
    "path": "tests/Middleware/AuthenticateAndRenewTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Middleware;\n\nuse Illuminate\\Http\\Response;\nuse Mockery;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Http\\Middleware\\AuthenticateAndRenew;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\nuse Tymon\\JWTAuth\\Test\\Stubs\\UserStub;\n\nclass AuthenticateAndRenewTest extends AbstractMiddlewareTest\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Http\\Middleware\\Authenticate|\\Tymon\\JWTAuth\\Http\\Middleware\\AuthenticateAndRenew\n     */\n    protected $middleware;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->middleware = new AuthenticateAndRenew($this->auth);\n    }\n\n    /** @test */\n    public function it_should_authenticate_a_user_and_return_a_new_token()\n    {\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n\n        $this->auth->shouldReceive('parseToken->authenticate')->once()->andReturn(new UserStub);\n\n        $this->auth->shouldReceive('refresh')->once()->andReturn('foo.bar.baz');\n\n        $response = $this->middleware->handle($this->request, function () {\n            return new Response;\n        });\n\n        $this->assertSame($response->headers->get('authorization'), 'Bearer foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_throw_an_unauthorized_exception_if_token_not_provided()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(false);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n\n    /** @test */\n    public function it_should_throw_an_unauthorized_exception_if_token_invalid()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->authenticate')->once()->andThrow(new TokenInvalidException);\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Middleware/AuthenticateTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Middleware;\n\nuse Mockery;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Http\\Middleware\\Authenticate;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\nuse Tymon\\JWTAuth\\Test\\Stubs\\UserStub;\n\nclass AuthenticateTest extends AbstractMiddlewareTest\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Http\\Middleware\\Authenticate\n     */\n    protected $middleware;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->middleware = new Authenticate($this->auth);\n    }\n\n    /** @test */\n    public function it_should_authenticate_a_user()\n    {\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->authenticate')->once()->andReturn(new UserStub);\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n\n    /** @test */\n    public function it_should_throw_an_unauthorized_exception_if_token_not_provided()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(false);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n\n    /** @test */\n    public function it_should_throw_an_unauthorized_exception_if_token_invalid()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->authenticate')->once()->andThrow(new TokenInvalidException);\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n\n    /** @test */\n    public function it_should_throw_an_unauthorized_exception_if_user_not_found()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->authenticate')->once()->andReturn(false);\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Middleware/CheckTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Middleware;\n\nuse Mockery;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Http\\Middleware\\Check;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\nuse Tymon\\JWTAuth\\Test\\Stubs\\UserStub;\n\nclass CheckTest extends AbstractMiddlewareTest\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Http\\Middleware\\Check\n     */\n    protected $middleware;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->middleware = new Check($this->auth);\n    }\n\n    /** @test */\n    public function it_should_authenticate_a_user_if_a_token_is_present()\n    {\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->authenticate')->once()->andReturn(new UserStub);\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n\n    /** @test */\n    public function it_should_unset_the_exception_if_a_token_is_present()\n    {\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->authenticate')->once()->andThrow(new TokenInvalidException);\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n\n    /** @test */\n    public function it_should_do_nothing_if_a_token_is_not_present()\n    {\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(false);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->authenticate')->never();\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Middleware/RefreshTokenTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Middleware;\n\nuse Illuminate\\Http\\Response;\nuse Mockery;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Http\\Middleware\\RefreshToken;\nuse Tymon\\JWTAuth\\Http\\Parser\\Parser;\n\nclass RefreshTokenTest extends AbstractMiddlewareTest\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Http\\Middleware\\RefreshToken\n     */\n    protected $middleware;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->middleware = new RefreshToken($this->auth);\n    }\n\n    /** @test */\n    public function it_should_refresh_a_token()\n    {\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->refresh')->once()->andReturn('foo.bar.baz');\n\n        $response = $this->middleware->handle($this->request, function () {\n            return new Response;\n        });\n\n        $this->assertSame($response->headers->get('authorization'), 'Bearer foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_throw_an_unauthorized_exception_if_token_not_provided()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(false);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n\n    /** @test */\n    public function it_should_throw_an_unauthorized_exception_if_token_invalid()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $parser = Mockery::mock(Parser::class);\n        $parser->shouldReceive('hasToken')->once()->andReturn(true);\n\n        $this->auth->shouldReceive('parser')->andReturn($parser);\n\n        $this->auth->parser()->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth->parser());\n        $this->auth->shouldReceive('parseToken->refresh')->once()->andThrow(new TokenInvalidException);\n\n        $this->middleware->handle($this->request, function () {\n            //\n        });\n    }\n}\n"
  },
  {
    "path": "tests/PayloadTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse BadMethodCallException;\nuse Mockery;\nuse Tymon\\JWTAuth\\Claims\\Audience;\nuse Tymon\\JWTAuth\\Claims\\Claim;\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Exceptions\\PayloadException;\nuse Tymon\\JWTAuth\\Payload;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass PayloadTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Tymon\\JWTAuth\\Validators\\PayloadValidator\n     */\n    protected $validator;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\Payload\n     */\n    protected $payload;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->payload = $this->getTestPayload();\n    }\n\n    /**\n     * @param  array  $extraClaims\n     * @return \\Tymon\\JWTAuth\\Payload\n     */\n    private function getTestPayload(array $extraClaims = [])\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n\n        if ($extraClaims) {\n            $claims = array_merge($claims, $extraClaims);\n        }\n\n        $collection = Collection::make($claims);\n\n        $this->validator = Mockery::mock(PayloadValidator::class);\n        $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);\n\n        return new Payload($collection, $this->validator);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_trying_to_add_to_the_payload()\n    {\n        $this->expectException(PayloadException::class);\n        $this->expectExceptionMessage('The payload is immutable');\n\n        $this->payload['foo'] = 'bar';\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_trying_to_remove_a_key_from_the_payload()\n    {\n        $this->expectException(PayloadException::class);\n        $this->expectExceptionMessage('The payload is immutable');\n\n        unset($this->payload['foo']);\n    }\n\n    /** @test */\n    public function it_should_cast_the_payload_to_a_string_as_json()\n    {\n        $this->assertSame((string) $this->payload, json_encode($this->payload->get(), JSON_UNESCAPED_SLASHES));\n        $this->assertJsonStringEqualsJsonString((string) $this->payload, json_encode($this->payload->get()));\n    }\n\n    /** @test */\n    public function it_should_allow_array_access_on_the_payload()\n    {\n        $this->assertTrue(isset($this->payload['iat']));\n        $this->assertSame($this->payload['sub'], 1);\n        $this->assertArrayHasKey('exp', $this->payload);\n    }\n\n    /** @test */\n    public function it_should_get_properties_of_payload_via_get_method()\n    {\n        $this->assertIsArray($this->payload->get());\n        $this->assertSame($this->payload->get('sub'), 1);\n\n        $this->assertSame(\n            $this->payload->get(function () {\n                return 'jti';\n            }),\n            'foo'\n        );\n    }\n\n    /** @test */\n    public function it_should_get_multiple_properties_when_passing_an_array_to_the_get_method()\n    {\n        $values = $this->payload->get(['sub', 'jti']);\n\n        $sub = $values[0];\n        $jti = $values[1];\n\n        $this->assertIsArray($values);\n        $this->assertSame($sub, 1);\n        $this->assertSame($jti, 'foo');\n    }\n\n    /** @test */\n    public function it_should_determine_whether_the_payload_has_a_claim()\n    {\n        $this->assertTrue($this->payload->has(new Subject(1)));\n        $this->assertFalse($this->payload->has(new Audience(1)));\n    }\n\n    /** @test */\n    public function it_should_magically_get_a_property()\n    {\n        $sub = $this->payload->getSubject();\n        $jti = $this->payload->getJwtId();\n        $iss = $this->payload->getIssuer();\n\n        $this->assertSame($sub, 1);\n        $this->assertSame($jti, 'foo');\n        $this->assertSame($iss, 'http://example.com');\n    }\n\n    /** @test */\n    public function it_should_invoke_the_instance_as_a_callable()\n    {\n        $payload = $this->payload;\n\n        $sub = $payload('sub');\n        $jti = $payload('jti');\n        $iss = $payload('iss');\n\n        $this->assertSame($sub, 1);\n        $this->assertSame($jti, 'foo');\n        $this->assertSame($iss, 'http://example.com');\n\n        $this->assertSame($payload(), $this->payload->toArray());\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_magically_getting_a_property_that_does_not_exist()\n    {\n        $this->expectException(BadMethodCallException::class);\n        $this->expectExceptionMessage('The claim [Foo] does not exist on the payload');\n\n        $this->payload->getFoo();\n    }\n\n    /** @test */\n    public function it_should_get_the_claims()\n    {\n        $claims = $this->payload->getClaims();\n\n        $this->assertInstanceOf(Expiration::class, $claims['exp']);\n        $this->assertInstanceOf(JwtId::class, $claims['jti']);\n        $this->assertInstanceOf(Subject::class, $claims['sub']);\n\n        $this->assertContainsOnlyInstancesOf(Claim::class, $claims);\n    }\n\n    /** @test */\n    public function it_should_get_the_object_as_json()\n    {\n        $this->assertJsonStringEqualsJsonString(json_encode($this->payload), $this->payload->toJson());\n    }\n\n    /** @test */\n    public function it_should_count_the_claims()\n    {\n        $this->assertSame(6, $this->payload->count());\n        $this->assertCount(6, $this->payload);\n    }\n\n    /** @test */\n    public function it_should_match_values()\n    {\n        $values = $this->payload->toArray();\n        $values['sub'] = (string) $values['sub'];\n\n        $this->assertTrue($this->payload->matches($values));\n    }\n\n    /** @test */\n    public function it_should_match_strict_values()\n    {\n        $values = $this->payload->toArray();\n\n        $this->assertTrue($this->payload->matchesStrict($values));\n        $this->assertTrue($this->payload->matches($values, true));\n    }\n\n    /** @test */\n    public function it_should_not_match_empty_values()\n    {\n        $this->assertFalse($this->payload->matches([]));\n    }\n\n    /** @test */\n    public function it_should_not_match_values()\n    {\n        $values = $this->payload->toArray();\n        $values['sub'] = 'dummy_subject';\n\n        $this->assertFalse($this->payload->matches($values));\n    }\n\n    /** @test */\n    public function it_should_not_match_strict_values()\n    {\n        $values = $this->payload->toArray();\n        $values['sub'] = (string) $values['sub'];\n\n        $this->assertFalse($this->payload->matchesStrict($values));\n        $this->assertFalse($this->payload->matches($values, true));\n    }\n\n    /** @test */\n    public function it_should_not_match_a_non_existing_claim()\n    {\n        $values = ['foo' => 'bar'];\n\n        $this->assertFalse($this->payload->matches($values));\n    }\n}\n"
  },
  {
    "path": "tests/Providers/Auth/IlluminateTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Providers\\Auth;\n\nuse Illuminate\\Contracts\\Auth\\Guard;\nuse Mockery;\nuse Tymon\\JWTAuth\\Providers\\Auth\\Illuminate as Auth;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nclass IlluminateTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Illuminate\\Contracts\\Auth\\Guard\n     */\n    protected $authManager;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\Providers\\Auth\\Illuminate\n     */\n    protected $auth;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->authManager = Mockery::mock(Guard::class);\n        $this->auth = new Auth($this->authManager);\n    }\n\n    /** @test */\n    public function it_should_return_true_if_credentials_are_valid()\n    {\n        $this->authManager->shouldReceive('once')->once()->with(['email' => 'foo@bar.com', 'password' => 'foobar'])->andReturn(true);\n        $this->assertTrue($this->auth->byCredentials(['email' => 'foo@bar.com', 'password' => 'foobar']));\n    }\n\n    /** @test */\n    public function it_should_return_true_if_user_is_found()\n    {\n        $this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andReturn(true);\n        $this->assertTrue($this->auth->byId(123));\n    }\n\n    /** @test */\n    public function it_should_return_false_if_user_is_not_found()\n    {\n        $this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andReturn(false);\n        $this->assertFalse($this->auth->byId(123));\n    }\n\n    /** @test */\n    public function it_should_return_the_currently_authenticated_user()\n    {\n        $this->authManager->shouldReceive('user')->once()->andReturn((object) ['id' => 1]);\n        $this->assertSame($this->auth->user()->id, 1);\n    }\n}\n"
  },
  {
    "path": "tests/Providers/JWT/LcobucciTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Providers\\JWT;\n\nuse Illuminate\\Support\\Str;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Providers\\JWT\\Lcobucci;\nuse Tymon\\JWTAuth\\Providers\\JWT\\Provider;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\n\nclass LcobucciTest extends AbstractTestCase\n{\n    /** @test */\n    public function it_can_encode_claims_using_a_symmetric_key()\n    {\n        $payload = [\n            'sub' => 1,\n            'exp' => $exp = $this->testNowTimestamp + 3600,\n            'iat' => $iat = $this->testNowTimestamp,\n            'iss' => '/foo',\n            'custom_claim' => 'foobar',\n        ];\n\n        $token = $this->getProvider(Str::random(64), Provider::ALGO_HS256)->encode($payload);\n        [$header, $payload, $signature] = explode('.', $token);\n\n        $claims = json_decode(base64_decode($payload), true);\n        $headerValues = json_decode(base64_decode($header), true);\n\n        $this->assertEquals(Provider::ALGO_HS256, $headerValues['alg']);\n        $this->assertIsString($signature);\n\n        $this->assertEquals('1', $claims['sub']);\n        $this->assertEquals('/foo', $claims['iss']);\n        $this->assertEquals('foobar', $claims['custom_claim']);\n        $this->assertEquals($exp, $claims['exp']);\n        $this->assertEquals($iat, $claims['iat']);\n    }\n\n    /** @test */\n    public function it_can_encode_and_decode_a_token_using_a_symmetric_key()\n    {\n        $payload = [\n            'sub' => 1,\n            'exp' => $exp = $this->testNowTimestamp + 3600,\n            'iat' => $iat = $this->testNowTimestamp,\n            'iss' => '/foo',\n            'custom_claim' => 'foobar',\n        ];\n\n        $provider = $this->getProvider(Str::random(64), Provider::ALGO_HS256);\n\n        $token = $provider->encode($payload);\n        $claims = $provider->decode($token);\n\n        $this->assertEquals('1', $claims['sub']);\n        $this->assertEquals('/foo', $claims['iss']);\n        $this->assertEquals('foobar', $claims['custom_claim']);\n        $this->assertEquals($exp, $claims['exp']);\n        $this->assertEquals($iat, $claims['iat']);\n    }\n\n    /** @test */\n    public function it_can_encode_and_decode_a_token_using_an_asymmetric_RS256_key()\n    {\n        $payload = [\n            'sub' => 1,\n            'exp' => $exp = $this->testNowTimestamp + 3600,\n            'iat' => $iat = $this->testNowTimestamp,\n            'iss' => '/foo',\n            'custom_claim' => 'foobar',\n        ];\n\n        $provider = $this->getProvider(\n            Str::random(64),\n            Provider::ALGO_RS256,\n            ['private' => $this->getDummyPrivateKey(), 'public' => $this->getDummyPublicKey()]\n        );\n\n        $token = $provider->encode($payload);\n\n        $header = json_decode(base64_decode(head(explode('.', $token))), true);\n        $this->assertEquals(Provider::ALGO_RS256, $header['alg']);\n\n        $claims = $provider->decode($token);\n\n        $this->assertEquals('1', $claims['sub']);\n        $this->assertEquals('/foo', $claims['iss']);\n        $this->assertEquals('foobar', $claims['custom_claim']);\n        $this->assertEquals($exp, $claims['exp']);\n        $this->assertEquals($iat, $claims['iat']);\n    }\n\n    /** @test */\n    public function it_can_encode_and_decode_a_token_with_nbf_jti_and_aud_claims()\n    {\n        $payload = [\n            'sub' => 1,\n            'exp' => $exp = $this->testNowTimestamp + 3600,\n            'iat' => $iat = $this->testNowTimestamp,\n            'nbf' => $nbf = $this->testNowTimestamp,\n            'jti' => $jti = 'unique-token-id',\n            'iss' => '/foo',\n            'aud' => $aud = 'my-audience',\n            'custom_claim' => 'foobar',\n        ];\n\n        $provider = $this->getProvider(Str::random(64), Provider::ALGO_HS256);\n\n        $token = $provider->encode($payload);\n        $claims = $provider->decode($token);\n\n        $this->assertEquals('1', $claims['sub']);\n        $this->assertEquals('/foo', $claims['iss']);\n        $this->assertEquals('foobar', $claims['custom_claim']);\n        $this->assertEquals($exp, $claims['exp']);\n        $this->assertEquals($iat, $claims['iat']);\n        $this->assertEquals($nbf, $claims['nbf']);\n        $this->assertEquals($jti, $claims['jti']);\n        $this->assertEquals([$aud], $claims['aud']);\n    }\n\n    /** @test */\n    public function it_can_encode_and_decode_a_token_using_an_asymmetric_ES256_key()\n    {\n        $payload = [\n            'sub' => 1,\n            'exp' => $exp = $this->testNowTimestamp + 3600,\n            'iat' => $iat = $this->testNowTimestamp,\n            'iss' => '/foo',\n            'custom_claim' => 'foobar',\n        ];\n\n        $provider = $this->getProvider(\n            Str::random(64),\n            Provider::ALGO_ES256,\n            ['private' => $this->getDummyEcPrivateKey(), 'public' => $this->getDummyEcPublicKey()]\n        );\n\n        $token = $provider->encode($payload);\n\n        $header = json_decode(base64_decode(head(explode('.', $token))), true);\n        $this->assertEquals(Provider::ALGO_ES256, $header['alg']);\n\n        $claims = $provider->decode($token);\n\n        $this->assertEquals('1', $claims['sub']);\n        $this->assertEquals('/foo', $claims['iss']);\n        $this->assertEquals('foobar', $claims['custom_claim']);\n        $this->assertEquals($exp, $claims['exp']);\n        $this->assertEquals($iat, $claims['iat']);\n    }\n\n    /** @test */\n    public function it_should_throw_an_invalid_exception_when_the_payload_could_not_be_encoded()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('Could not create token:');\n\n        $payload = [\n            'sub' => 1,\n            'exp' => $this->testNowTimestamp + 3600,\n            'iat' => $this->testNowTimestamp,\n            'iss' => '/foo',\n            'custom_claim' => 'foobar',\n            'invalid_utf8' => \"\\xB1\\x31\", // cannot be encoded as JSON\n        ];\n\n        $this->getProvider(Str::random(64), Provider::ALGO_HS256)->encode($payload);\n    }\n\n    /** @test */\n    public function it_should_throw_a_token_invalid_exception_when_the_token_could_not_be_decoded_due_to_a_bad_signature()\n    {\n        $this->expectException(TokenInvalidException::class);\n        $this->expectExceptionMessage('Token Signature could not be verified.');\n\n        // This has a different secret than the one used to encode the token\n        $this->getProvider(Str::random(64), Provider::ALGO_HS256)\n            ->decode('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiZXhwIjoxNjQ5MjYxMDY1LCJpYXQiOjE2NDkyNTc0NjUsImlzcyI6Ii9mb28iLCJjdXN0b21fY2xhaW0iOiJmb29iYXIifQ.jamiInQiin-1RUviliPjZxl0MLEnQnVTbr2sGooeXBY');\n    }\n\n    /** @test */\n    public function it_should_throw_a_token_invalid_exception_when_the_token_could_not_be_decoded_due_to_tampered_token()\n    {\n        $this->expectException(TokenInvalidException::class);\n        $this->expectExceptionMessage('Token Signature could not be verified.');\n\n        // This sub claim for this token has been tampered with so the signature will not match\n        $this->getProvider(Str::random(64), Provider::ALGO_HS256)\n            ->decode('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiZXhwIjoxNjQ5MjYxMDY1LCJpYXQiOjE2NDkyNTc0NjUsImlzcyI6Ii9mb29iYXIiLCJjdXN0b21fY2xhaW0iOiJmb29iYXIifQ.jamiInQiin-1RUviliPjZxl0MLEnQnVTbr2sGooeXBY');\n    }\n\n    /** @test */\n    public function it_should_throw_a_token_invalid_exception_when_the_token_could_not_be_decoded()\n    {\n        $this->expectException(TokenInvalidException::class);\n        $this->expectExceptionMessage('Could not decode token:');\n\n        $this->getProvider('secret', Provider::ALGO_HS256)->decode('foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_the_algorithm_passed_is_invalid()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('The given algorithm could not be found');\n\n        $this->getProvider('secret', 'INVALID_ALGO')->decode('foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_no_symmetric_key_is_provided_when_encoding()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('Secret is not set.');\n\n        $this->getProvider(null, Provider::ALGO_HS256)->encode(['sub' => 1]);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_no_symmetric_key_is_provided_when_decoding()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('Secret is not set.');\n\n        $this->getProvider(null, Provider::ALGO_HS256)->decode('foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_no_asymmetric_public_key_is_provided()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('Public key is not set.');\n\n        $this->getProvider(\n            'does_not_matter',\n            Provider::ALGO_RS256,\n            ['private' => $this->getDummyPrivateKey(), 'public' => null]\n        )->decode('foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_no_asymmetric_private_key_is_provided()\n    {\n        $this->expectException(JWTException::class);\n        $this->expectExceptionMessage('Private key is not set.');\n\n        $this->getProvider(\n            'does_not_matter',\n            Provider::ALGO_RS256,\n            ['private' => null, 'public' => $this->getDummyPublicKey()]\n        )->encode(['sub' => 1]);\n    }\n\n    /** @test */\n    public function it_should_return_the_public_key()\n    {\n        $provider = $this->getProvider(\n            'does_not_matter',\n            Provider::ALGO_RS256,\n            $keys = ['private' => $this->getDummyPrivateKey(), 'public' => $this->getDummyPublicKey()]\n        );\n\n        $this->assertSame($keys['public'], $provider->getPublicKey());\n    }\n\n    /** @test */\n    public function it_should_return_the_keys()\n    {\n        $provider = $this->getProvider(\n            'does_not_matter',\n            Provider::ALGO_RS256,\n            $keys = ['private' => $this->getDummyPrivateKey(), 'public' => $this->getDummyPublicKey()]\n        );\n\n        $this->assertSame($keys, $provider->getKeys());\n    }\n\n    public function getProvider($secret, $algo, array $keys = [])\n    {\n        return new Lcobucci($secret, $algo, $keys);\n    }\n\n    public function getDummyPrivateKey()\n    {\n        return file_get_contents(__DIR__.'/../Keys/id_rsa');\n    }\n\n    public function getDummyPublicKey()\n    {\n        return file_get_contents(__DIR__.'/../Keys/id_rsa.pub');\n    }\n\n    public function getDummyEcPrivateKey()\n    {\n        return file_get_contents(__DIR__.'/../Keys/id_ecdsa');\n    }\n\n    public function getDummyEcPublicKey()\n    {\n        return file_get_contents(__DIR__.'/../Keys/id_ecdsa.pub');\n    }\n}\n"
  },
  {
    "path": "tests/Providers/JWT/ProviderTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Providers\\JWT;\n\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\nuse Tymon\\JWTAuth\\Test\\Stubs\\JWTProviderStub;\n\nclass ProviderTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Test\\Stubs\\JWTProviderStub\n     */\n    protected $provider;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->provider = new JWTProviderStub('secret', 'HS256', []);\n    }\n\n    /** @test */\n    public function it_should_set_the_algo()\n    {\n        $this->provider->setAlgo('HS512');\n\n        $this->assertSame('HS512', $this->provider->getAlgo());\n    }\n\n    /** @test */\n    public function it_should_set_the_secret()\n    {\n        $this->provider->setSecret('foo');\n\n        $this->assertSame('foo', $this->provider->getSecret());\n    }\n}\n"
  },
  {
    "path": "tests/Providers/Keys/id_ecdsa",
    "content": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIPKNCQlkD3SP1JniCj2RXvGlzp8NO9sYyQr05hdFlGKboAoGCCqGSM49\nAwEHoUQDQgAEhXUAmmzqpHbtmm4SY5ikZparlUyrmggNhDy8QoyNIlbrJzh6q0PF\ncrVbOchQZ2fGp0r+6o1tDTmz0AN3XWKJXw==\n-----END EC PRIVATE KEY-----\n"
  },
  {
    "path": "tests/Providers/Keys/id_ecdsa.pub",
    "content": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhXUAmmzqpHbtmm4SY5ikZparlUyr\nmggNhDy8QoyNIlbrJzh6q0PFcrVbOchQZ2fGp0r+6o1tDTmz0AN3XWKJXw==\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "tests/Providers/Keys/id_rsa",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDTvwE87MtgREYL\nTL4aHhQo3ZzogmxxvMUsKnPzyxRs1YrXOSOpwN0npsXarBKKVIUMNLfFODp/vnQn\n2Zp06N8XG59WAOKwvC4MfxLDQkA+JXggzHlkbVoTN+dUkdYIFqSKuAPGwiWToRK2\nSxEhij3rE2FON8jQZvDxZkiP9a4vxJO3OTPQwKredXFiObsXD/c3RtLFhKctjCyH\nOIrP0bQEsee/m7JNtG4ry6BPusN6wb+vJo5ieBYPa3c19akNq6q/nYWhplhkkJSu\naOrL5xXEFzI5TvcvnXR568GVcxK8YLfFkdxpsXGt5rAbeh0h/U5kILEAqv8P9PGT\nZpicKbrnAgMBAAECggEAd3yTQEQHR91/ASVfKPHMQns77eCbPVtekFusbugsMHYY\nEPdHbqVMpvFvOMRc+f5Tzd15ziq6qBdbCJm8lThLm4iU0z1QrpaiDZ8vgUvDYM5Y\nCXoZDli+uZWUTp60/n94fmb0ipZIChScsI2PrzOJWTvobvD/uso8MJydWc8zafQm\nuqYzygOfjFZvU4lSfgzpefhpquy0JUy5TiKRmGUnwLb3TtcsVavjsn4QmNwLYgOF\n2OE+R12ex3pAKTiRE6FcnE1xFIo1GKhBa2Otgw3MDO6Gg+kn8Q4alKz6C6RRlgaH\nR7sYzEfJhsk/GGFTYOzXKQz2lSaStKt9wKCor04RcQKBgQDzPOu5jCTfayUo7xY2\njHtiogHyKLLObt9l3qbwgXnaD6rnxYNvCrA0OMvT+iZXsFZKJkYzJr8ZOxOpPROk\n10WdOaefiwUyL5dypueSwlIDwVm+hI4Bs82MajHtzOozh+73wA+aw5rPs84Uix9w\nVbbwaVR6qP/BV09yJYS5kQ7fmwKBgQDe2xjywX2d2MC+qzRr+LfU+1+gq0jjhBCX\nWHqRN6IECB0xTnXUf9WL/VCoI1/55BhdbbEja+4btYgcXSPmlXBIRKQ4VtFfVmYB\nkPXeD8oZ7LyuNdCsbKNe+x1IHXDe6Wfs3L9ulCfXxeIE84wy3fd66mQahyXV9iD9\nCkuifMqUpQKBgQCiydHlY1LGJ/o9tA2Ewm5Na6mrvOs2V2Ox1NqbObwoYbX62eiF\n53xX5u8bVl5U75JAm+79it/4bd5RtKux9dUETbLOhwcaOFm+hM+VG/IxyzRZ2nMD\n1qcpY2U5BpxzknUvYF3RMTop6edxPk7zKpp9ubCtSu+oINvtxAhY/SkcIwKBgGP1\nupcImyO2GZ5shLL5eNubdSVILwV+M0LveOqyHYXZbd6z5r5OKKcGFKuWUnJwEU22\n6gGNY9wh7M9sJ7JBzX9c6pwqtPcidda2AtJ8GpbOTUOG9/afNBhiYpv6OKqD3w2r\nZmJfKg/qvpqh83zNezgy8nvDqwDxyZI2j/5uIx/RAoGBAMWRmxtv6H2cKhibI/aI\nMTJM4QRjyPNxQqvAQsv+oHUbid06VK3JE+9iQyithjcfNOwnCaoO7I7qAj9QEfJS\nMZQc/W/4DHJebo2kd11yoXPVTXXOuEwLSKCejBXABBY0MPNuPUmiXeU0O3Tyi37J\nTUKzrgcd7NvlA41Y4xKcOqEA\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "tests/Providers/Keys/id_rsa.pub",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA078BPOzLYERGC0y+Gh4U\nKN2c6IJscbzFLCpz88sUbNWK1zkjqcDdJ6bF2qwSilSFDDS3xTg6f750J9madOjf\nFxufVgDisLwuDH8Sw0JAPiV4IMx5ZG1aEzfnVJHWCBakirgDxsIlk6EStksRIYo9\n6xNhTjfI0Gbw8WZIj/WuL8STtzkz0MCq3nVxYjm7Fw/3N0bSxYSnLYwshziKz9G0\nBLHnv5uyTbRuK8ugT7rDesG/ryaOYngWD2t3NfWpDauqv52FoaZYZJCUrmjqy+cV\nxBcyOU73L510eevBlXMSvGC3xZHcabFxreawG3odIf1OZCCxAKr/D/Txk2aYnCm6\n5wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "tests/Providers/Storage/IlluminateTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Providers\\Storage;\n\nuse Illuminate\\Contracts\\Cache\\Repository;\nuse Mockery;\nuse Tymon\\JWTAuth\\Providers\\Storage\\Illuminate as Storage;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\nuse Tymon\\JWTAuth\\Test\\Stubs\\TaggedStorage;\n\nclass IlluminateTest extends AbstractTestCase\n{\n    /**\n     * @var \\Mockery\\MockInterface|\\Illuminate\\Contracts\\Cache\\Repository\n     */\n    protected $cache;\n\n    /**\n     * @var \\Tymon\\JWTAuth\\Providers\\Storage\\Illuminate\n     */\n    protected $storage;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->cache = Mockery::mock(Repository::class);\n        $this->storage = new Storage($this->cache);\n    }\n\n    /** @test */\n    public function it_should_add_the_item_to_storage()\n    {\n        $this->cache->shouldReceive('put')->with('foo', 'bar', 10)->once();\n\n        $this->storage->add('foo', 'bar', 10);\n    }\n\n    /** @test */\n    public function it_should_add_the_item_to_storage_forever()\n    {\n        $this->cache->shouldReceive('forever')->with('foo', 'bar')->once();\n\n        $this->storage->forever('foo', 'bar');\n    }\n\n    /** @test */\n    public function it_should_get_an_item_from_storage()\n    {\n        $this->cache->shouldReceive('get')->with('foo')->once()->andReturn(['foo' => 'bar']);\n\n        $this->assertSame(['foo' => 'bar'], $this->storage->get('foo'));\n    }\n\n    /** @test */\n    public function it_should_remove_the_item_from_storage()\n    {\n        $this->cache->shouldReceive('forget')->with('foo')->once()->andReturn(true);\n\n        $this->assertTrue($this->storage->destroy('foo'));\n    }\n\n    /** @test */\n    public function it_should_remove_all_items_from_storage()\n    {\n        $this->cache->shouldReceive('flush')->withNoArgs()->once();\n\n        $this->storage->flush();\n    }\n\n    // Duplicate tests for tagged storage --------------------\n\n    /**\n     * Replace the storage with our one above that overrides the tag flag, and\n     * define expectations for tags() method.\n     *\n     * @return void\n     */\n    private function emulateTags()\n    {\n        $this->storage = new TaggedStorage($this->cache);\n\n        $this->cache->shouldReceive('tags')->with('tymon.jwt')->once()->andReturn(Mockery::self());\n    }\n\n    /** @test */\n    public function it_should_add_the_item_to_tagged_storage()\n    {\n        $this->emulateTags();\n        $this->cache->shouldReceive('put')->with('foo', 'bar', 10)->once();\n\n        $this->storage->add('foo', 'bar', 10);\n    }\n\n    /** @test */\n    public function it_should_add_the_item_to_tagged_storage_forever()\n    {\n        $this->emulateTags();\n        $this->cache->shouldReceive('forever')->with('foo', 'bar')->once();\n\n        $this->storage->forever('foo', 'bar');\n    }\n\n    /** @test */\n    public function it_should_get_an_item_from_tagged_storage()\n    {\n        $this->emulateTags();\n        $this->cache->shouldReceive('get')->with('foo')->once()->andReturn(['foo' => 'bar']);\n\n        $this->assertSame(['foo' => 'bar'], $this->storage->get('foo'));\n    }\n\n    /** @test */\n    public function it_should_remove_the_item_from_tagged_storage()\n    {\n        $this->emulateTags();\n        $this->cache->shouldReceive('forget')->with('foo')->once()->andReturn(true);\n\n        $this->assertTrue($this->storage->destroy('foo'));\n    }\n\n    /** @test */\n    public function it_should_remove_all_tagged_items_from_storage()\n    {\n        $this->emulateTags();\n        $this->cache->shouldReceive('flush')->withNoArgs()->once();\n\n        $this->storage->flush();\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/JWTProviderStub.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Stubs;\n\nuse Tymon\\JWTAuth\\Providers\\JWT\\Provider;\n\nclass JWTProviderStub extends Provider\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected function isAsymmetric()\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/LaravelUserStub.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Stubs;\n\nuse Illuminate\\Contracts\\Auth\\Authenticatable;\nuse Tymon\\JWTAuth\\Contracts\\JWTSubject;\n\nclass LaravelUserStub extends UserStub implements Authenticatable, JWTSubject\n{\n    public function getAuthIdentifierName()\n    {\n        //\n    }\n\n    public function getAuthIdentifier()\n    {\n        //\n    }\n\n    public function getAuthPassword()\n    {\n        //\n    }\n\n    public function getRememberToken()\n    {\n        //\n    }\n\n    public function setRememberToken($value)\n    {\n        //\n    }\n\n    public function getRememberTokenName()\n    {\n        //\n    }\n\n    public function getAuthPasswordName()\n    {\n        return 'password';\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/TaggedStorage.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Stubs;\n\nuse Tymon\\JWTAuth\\Providers\\Storage\\Illuminate as Storage;\n\nclass TaggedStorage extends Storage\n{\n    // It's extremely challenging to test the actual functionality of the provider's\n    // cache() function, because it relies on calling method_exists on methods that\n    // aren't defined in the interface. Getting those conditionals to behave as expected\n    // would be a lot of finicky work compared to verifying their functionality by hand.\n    // So instead we'll just set this value manually...\n    protected $supportsTags = true;\n}\n"
  },
  {
    "path": "tests/Stubs/UserStub.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Stubs;\n\nuse Tymon\\JWTAuth\\Contracts\\JWTSubject;\n\nclass UserStub implements JWTSubject\n{\n    public function getJWTIdentifier()\n    {\n        return 1;\n    }\n\n    public function getJWTCustomClaims()\n    {\n        return [\n            'foo' => 'bar',\n            'role' => 'admin',\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/TokenTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test;\n\nuse Tymon\\JWTAuth\\Token;\n\nclass TokenTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Token\n     */\n    protected $token;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->token = new Token('foo.bar.baz');\n    }\n\n    /** @test */\n    public function it_should_return_the_token_when_casting_to_a_string()\n    {\n        $this->assertEquals((string) $this->token, $this->token);\n    }\n\n    /** @test */\n    public function it_should_return_the_token_when_calling_get_method()\n    {\n        $this->assertIsString($this->token->get());\n    }\n}\n"
  },
  {
    "path": "tests/Validators/PayloadValidatorTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Validators;\n\nuse Tymon\\JWTAuth\\Claims\\Collection;\nuse Tymon\\JWTAuth\\Claims\\Expiration;\nuse Tymon\\JWTAuth\\Claims\\IssuedAt;\nuse Tymon\\JWTAuth\\Claims\\Issuer;\nuse Tymon\\JWTAuth\\Claims\\JwtId;\nuse Tymon\\JWTAuth\\Claims\\NotBefore;\nuse Tymon\\JWTAuth\\Claims\\Subject;\nuse Tymon\\JWTAuth\\Exceptions\\InvalidClaimException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenExpiredException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\nuse Tymon\\JWTAuth\\Validators\\PayloadValidator;\n\nclass PayloadValidatorTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Validators\\PayloadValidator\n     */\n    protected $validator;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->validator = new PayloadValidator;\n    }\n\n    /** @test */\n    public function it_should_return_true_when_providing_a_valid_payload()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 3600),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->assertTrue($this->validator->isValid($collection));\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_providing_an_expired_payload()\n    {\n        $this->expectException(TokenExpiredException::class);\n        $this->expectExceptionMessage('Token has expired');\n\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp - 1440),\n            new NotBefore($this->testNowTimestamp - 3660),\n            new IssuedAt($this->testNowTimestamp - 3660),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->check($collection);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_providing_an_invalid_nbf_claim()\n    {\n        $this->expectException(TokenInvalidException::class);\n        $this->expectExceptionMessage('Not Before (nbf) timestamp cannot be in the future');\n\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 1440),\n            new NotBefore($this->testNowTimestamp + 3660),\n            new IssuedAt($this->testNowTimestamp - 3660),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->check($collection);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_providing_an_invalid_iat_claim()\n    {\n        $this->expectException(InvalidClaimException::class);\n        $this->expectExceptionMessage('Invalid value provided for claim [iat]');\n\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp + 1440),\n            new NotBefore($this->testNowTimestamp - 3660),\n            new IssuedAt($this->testNowTimestamp + 3660),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->check($collection);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_providing_an_invalid_payload()\n    {\n        $this->expectException(TokenInvalidException::class);\n        $this->expectExceptionMessage('JWT payload does not contain the required claims');\n\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->check($collection);\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_when_providing_an_invalid_expiry()\n    {\n        $this->expectException(InvalidClaimException::class);\n        $this->expectExceptionMessage('Invalid value provided for claim [exp]');\n\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration('foo'),\n            new NotBefore($this->testNowTimestamp - 3660),\n            new IssuedAt($this->testNowTimestamp + 3660),\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->check($collection);\n    }\n\n    /** @test */\n    public function it_should_set_the_required_claims()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->assertTrue($this->validator->setRequiredClaims(['iss', 'sub'])->isValid($collection));\n    }\n\n    /** @test */\n    public function it_should_check_the_token_in_the_refresh_context()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp - 1000),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp - 2600), // this is LESS than the refresh ttl at 1 hour\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->assertTrue(\n            $this->validator->setRefreshFlow()->setRefreshTTL(60)->isValid($collection)\n        );\n    }\n\n    /** @test */\n    public function it_should_return_true_if_the_refresh_ttl_is_null()\n    {\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp - 1000),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp - 2600), // this is LESS than the refresh ttl at 1 hour\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->assertTrue(\n            $this->validator->setRefreshFlow()->setRefreshTTL(null)->isValid($collection)\n        );\n    }\n\n    /** @test */\n    public function it_should_throw_an_exception_if_the_token_cannot_be_refreshed()\n    {\n        $this->expectException(TokenExpiredException::class);\n        $this->expectExceptionMessage('Token has expired and can no longer be refreshed');\n\n        $claims = [\n            new Subject(1),\n            new Issuer('http://example.com'),\n            new Expiration($this->testNowTimestamp),\n            new NotBefore($this->testNowTimestamp),\n            new IssuedAt($this->testNowTimestamp - 5000), // this is MORE than the refresh ttl at 1 hour, so is invalid\n            new JwtId('foo'),\n        ];\n\n        $collection = Collection::make($claims);\n\n        $this->validator->setRefreshFlow()->setRefreshTTL(60)->check($collection);\n    }\n}\n"
  },
  {
    "path": "tests/Validators/TokenValidatorTest.php",
    "content": "<?php\n\n/*\n * This file is part of jwt-auth.\n *\n * (c) Sean Tymon <tymon148@gmail.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Tymon\\JWTAuth\\Test\\Validators;\n\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\nuse Tymon\\JWTAuth\\Test\\AbstractTestCase;\nuse Tymon\\JWTAuth\\Validators\\TokenValidator;\n\nclass TokenValidatorTest extends AbstractTestCase\n{\n    /**\n     * @var \\Tymon\\JWTAuth\\Validators\\TokenValidator\n     */\n    protected $validator;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->validator = new TokenValidator;\n    }\n\n    /** @test */\n    public function it_should_return_true_when_providing_a_well_formed_token()\n    {\n        $this->assertTrue($this->validator->isValid('one.two.three'));\n    }\n\n    /**\n     * @test\n     *\n     * @dataProvider \\Tymon\\JWTAuth\\Test\\Validators\\TokenValidatorTest::dataProviderMalformedTokens\n     *\n     * @param  string  $token\n     */\n    public function it_should_return_false_when_providing_a_malformed_token($token)\n    {\n        $this->assertFalse($this->validator->isValid($token));\n    }\n\n    /**\n     * @test\n     *\n     * @dataProvider \\Tymon\\JWTAuth\\Test\\Validators\\TokenValidatorTest::dataProviderMalformedTokens\n     */\n    public function it_should_throw_an_exception_when_providing_a_malformed_token($token)\n    {\n        $this->expectException(TokenInvalidException::class);\n        $this->expectExceptionMessage('Malformed token');\n\n        $this->validator->check($token);\n    }\n\n    /**\n     * @test\n     *\n     * @dataProvider \\Tymon\\JWTAuth\\Test\\Validators\\TokenValidatorTest::dataProviderTokensWithWrongSegmentsNumber\n     */\n    public function it_should_return_false_when_providing_a_token_with_wrong_segments_number($token)\n    {\n        $this->assertFalse($this->validator->isValid($token));\n    }\n\n    /**\n     * @test\n     *\n     * @dataProvider \\Tymon\\JWTAuth\\Test\\Validators\\TokenValidatorTest::dataProviderTokensWithWrongSegmentsNumber\n     */\n    public function it_should_throw_an_exception_when_providing_a_malformed_token_with_wrong_segments_number($token)\n    {\n        $this->expectException(TokenInvalidException::class);\n        $this->expectExceptionMessage('Wrong number of segments');\n\n        $this->validator->check($token);\n    }\n\n    public function dataProviderMalformedTokens()\n    {\n        return [\n            ['one.two.'],\n            ['.two.'],\n            ['.two.three'],\n            ['one..three'],\n            ['..'],\n            [' . . '],\n            [' one . two . three '],\n        ];\n    }\n\n    public function dataProviderTokensWithWrongSegmentsNumber()\n    {\n        return [\n            ['one.two'],\n            ['one.two.three.four'],\n            ['one.two.three.four.five'],\n        ];\n    }\n}\n"
  }
]