{"id":13673862,"url":"https://github.com/zfcampus/zf-oauth2","last_synced_at":"2025-04-28T13:31:56.596Z","repository":{"id":11697723,"uuid":"14211432","full_name":"zfcampus/zf-oauth2","owner":"zfcampus","description":"OAuth2 server module for ZF2","archived":true,"fork":false,"pushed_at":"2020-01-20T17:28:56.000Z","size":898,"stargazers_count":104,"open_issues_count":18,"forks_count":92,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-11-11T14:39:41.438Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zfcampus.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-11-07T18:01:53.000Z","updated_at":"2024-07-26T02:54:06.000Z","dependencies_parsed_at":"2022-09-15T21:51:24.453Z","dependency_job_id":null,"html_url":"https://github.com/zfcampus/zf-oauth2","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfcampus%2Fzf-oauth2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfcampus%2Fzf-oauth2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfcampus%2Fzf-oauth2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfcampus%2Fzf-oauth2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zfcampus","download_url":"https://codeload.github.com/zfcampus/zf-oauth2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251319757,"owners_count":21570451,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T11:00:26.497Z","updated_at":"2025-04-28T13:31:51.508Z","avatar_url":"https://github.com/zfcampus.png","language":"PHP","funding_links":[],"categories":["Modules"],"sub_categories":[],"readme":"# zf-oauth2\n\n\u003e ## Repository abandoned 2019-12-31\n\u003e\n\u003e This repository has moved to [laminas-api-tools/api-tools-oauth2](https://github.com/laminas-api-tools/api-tools-oauth2).\n\n[![Build Status](https://secure.travis-ci.org/zfcampus/zf-oauth2.svg?branch=master)](https://secure.travis-ci.org/zfcampus/zf-oauth2)\n[![Coverage Status](https://coveralls.io/repos/github/zfcampus/zf-oauth2/badge.svg?branch=master)](https://coveralls.io/github/zfcampus/zf-oauth2?branch=master)\n\nZF module for [OAuth2](http://oauth.net/2/) authentication.\n\nThis module uses the [oauth2-server-php](https://github.com/bshaffer/oauth2-server-php)\nlibrary by Brent Shaffer to provide OAuth2 support.\n\n## Requirements\n  \nPlease see the [composer.json](composer.json) file.\n\n## Installation\n\nYou can install using:\n\n```bash\n$ composer require zfcampus/zf-oauth2\n```\n\nIf you are using ext/mongodb, you will also need to install a compatibility\npackage:\n\n```bash\n$ composer require alcaeus/mongo-php-adapter\n```\n\nFinally, you will need to add the following modules to your application's\nconfiguration:\n\n```php\n'modules' =\u003e [\n    /* ... */\n    'ZF\\ApiProblem',\n    'ZF\\ContentNegotiation',\n    'ZF\\OAuth2',\n],\n```\n\n\u003e ### zf-component-installer\n\u003e\n\u003e If you use [zf-component-installer](https://github.com/zendframework/zf-component-installer),\n\u003e that plugin will install zf-oauth2 and its other Apigility dependencies as\n\u003e modules for you.\n\n## Configuration\n\nThis module uses any PDO-suported database to manage the OAuth2 information\n(users, client, token, etc).  The database structure is stored in\n`data/db_oauth2.sql`.\n\n```sql\nCREATE TABLE oauth_clients (\n    client_id VARCHAR(80) NOT NULL,\n    client_secret VARCHAR(80) NOT NULL,\n    redirect_uri VARCHAR(2000) NOT NULL,\n    grant_types VARCHAR(80),\n    scope VARCHAR(2000),\n    user_id VARCHAR(255),\n    CONSTRAINT clients_client_id_pk PRIMARY KEY (client_id)\n);\nCREATE TABLE oauth_access_tokens (\n    access_token VARCHAR(40) NOT NULL,\n    client_id VARCHAR(80) NOT NULL,\n    user_id VARCHAR(255),\n    expires TIMESTAMP NOT NULL,\n    scope VARCHAR(2000),\n    CONSTRAINT access_token_pk PRIMARY KEY (access_token)\n);\nCREATE TABLE oauth_authorization_codes (\n    authorization_code VARCHAR(40) NOT NULL,\n    client_id VARCHAR(80) NOT NULL,\n    user_id VARCHAR(255),\n    redirect_uri VARCHAR(2000),\n    expires TIMESTAMP NOT NULL,\n    scope VARCHAR(2000),\n    id_token VARCHAR(2000),\n    CONSTRAINT auth_code_pk PRIMARY KEY (authorization_code)\n);\nCREATE TABLE oauth_refresh_tokens (\n    refresh_token VARCHAR(40) NOT NULL,\n    client_id VARCHAR(80) NOT NULL,\n    user_id VARCHAR(255),\n    expires TIMESTAMP NOT NULL,\n    scope VARCHAR(2000),\n    CONSTRAINT refresh_token_pk PRIMARY KEY (refresh_token)\n);\nCREATE TABLE oauth_users (\n    username VARCHAR(255) NOT NULL,\n    password VARCHAR(2000),\n    first_name VARCHAR(255),\n    last_name VARCHAR(255),\n    CONSTRAINT username_pk PRIMARY KEY (username)\n);\nCREATE TABLE oauth_scopes (\n    type VARCHAR(255) NOT NULL DEFAULT \"supported\",\n    scope VARCHAR(2000),\n    client_id VARCHAR (80),\n    is_default SMALLINT DEFAULT NULL\n);\nCREATE TABLE oauth_jwt (\n    client_id VARCHAR(80) NOT NULL,\n    subject VARCHAR(80),\n    public_key VARCHAR(2000),\n    CONSTRAINT jwt_client_id_pk PRIMARY KEY (client_id)\n);\n```\n\n\u003e ### PostgreSQL\n\u003e\n\u003e We also have a PostgreSQL-specific DDL in `data/db_oauth2_postgresql.sql`.\n\nFor security reasons, we encrypt the fields `client_secret` (table\n`oauth_clients`) and `password` (table `oauth_users`) using the\n[bcrypt](http://en.wikipedia.org/wiki/Bcrypt) algorithm (via the class\n[Zend\\Crypt\\Password\\Bcrypt](http://framework.zend.com/manual/2.2/en/modules/zend.crypt.password.html#bcrypt)).\n\nIn order to configure the zf-oauth2 module for database access, you need to copy\nthe file `config/oauth2.local.php.dist` to `config/autoload/oauth2.local.php` in\nyour ZF2 application, and edit it to provide your DB credentials (DNS, username,\npassword).\n\nWe also include a SQLite database in `data/dbtest.sqlite` that you can use in a\ntest environment.  In this database, you will find a test client account with\nthe `client_id` \"testclient\" and the `client_secret` \"testpass\".  If you want to\nuse this database, you can configure your `config/autoload/oauth2.local.php`\nfile as follow:\n\n```php\nreturn array(\n    'zf-oauth2' =\u003e array(\n        'db' =\u003e array(\n            'dsn' =\u003e 'sqlite:\u003cpath to zf-oauth2 module\u003e/data/dbtest.sqlite',\n        ),\n    ),\n);\n```\n\n## Mongo Configuration\n\nThe Mongo OAuth2 adapter wraps the bshaffer adapter by adding the same password encryption\nas the rest of apigility.  The collections needed are the same as above in the PDO\nadapter.  To create an OAuth2 client, insert a document like the following into the\noauth_clients collection:\n\n```javascript\n{\n    \"client_id\":     \"testclient\",\n    \"client_secret\": \"$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2\",\n    \"redirect_uri\":  \"/oauth/receivecode\",\n    \"grant_types\":   null\n}\n```\n\n## User ID Provider\n\nWhen a user requests an authorization code they may provide their user_id as a request parameter to\nthe `/oauth/authorize` route.  This will store the `user_id` in the `access_token`, `refresh_token`,\nand `authorization_code` tables as the user goes throught the oauth2 process.\n\nA user may be authenticated through `Zend\\Authentication\\AuthenticationService` or another\nauthentication means.  When a user must provide authentication before they may access the\n`/oauth/authorize` route, the authenticated user ID should be used. This is done with the service\nmanager alias `ZF\\OAuth2\\Provider\\UserId`.\n\nThe default User ID Provider uses the request query parameter `user_id` and is handled via the class\n`ZF\\OAuth2\\Provider\\UserId\\Request`.\n\nProvided with this repository is an alternative provider,\n`ZF\\OAuth2\\Provider\\UserId\\AuthorizationService`, which uses\n`Zend\\Authentication\\AuthenticationService` to fetch the identity.  To change the User ID Provider\nto use this service, change the `ZF\\OAuth2\\Provider\\UserId` service alias to point at it:\n\n```php\nreturn array(\n    'service_manager' =\u003e \n        'aliases' =\u003e array(\n            'ZF\\OAuth2\\Provider\\UserId' =\u003e 'ZF\\OAuth2\\Provider\\UserId\\AuthenticationService',\n        ),\n    ),\n);\n```\n\n## How to test OAuth2\n\nTo test the OAuth2 module, you have to add a `client_id` and a `client_secret`\ninto the oauth2 database. If you are using the SQLite test database, you don't\nneed to add a `client_id`; just use the default \"testclient\"/\"testpass\" account.\n\nBecause we encrypt the password using the `bcrypt` algorithm, you need to\nencrypt the password using the [Zend\\Crypt\\Password\\Bcrypt](http://framework.zend.com/manual/2.2/en/modules/zend.crypt.password.html#bcrypt)\nclass from Zend Framework 2. We provided a simple script in `/bin/bcrypt.php` to\ngenerate the hash value of a user's password. You can use this tool from the\ncommand line, with the following syntax:\n\n```bash\nphp bin/bcrypt.php testpass\n```\n\nwhere \"testpass\" is the user's password that you want to encrypt. The output of\nthe previous command will be the hash value of the user's password, a string of\n60 bytes like the following:\n\n```\n$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2\n```\n\nAfter the generation of the hash value of the password (`client_secret`), you can\nadd a new `client_id` in the database using the following SQL statement:\n\n```sql\nINSERT INTO oauth_clients (\n    client_id,\n    client_secret,\n    redirect_uri)\nVALUES (\n    \"testclient\",\n    \"$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2\",\n    \"/oauth/receivecode\"\n);\n```\n\nTo test the OAuth2 module, you can use an HTTP client like\n[HTTPie](https://github.com/jkbr/httpie) or [CURL](http://curl.haxx.se/).  The\nexamples below use HTTPie and the test account \"testclient\"/\"testpass\".\n\n## REQUEST TOKEN (client\\_credentials)\n\nYou can request an OAuth2 token using the following HTTPie command:\n\n```bash\nhttp --auth testclient:testpass -f POST http://\u003cURL of your ZF2 app\u003e/oauth grant_type=client_credentials\n```\n\nThis POST requests a new token to the OAuth2 server using the *client_credentials*\nmode. This is typical in machine-to-machine interaction for application access.\nIf everything works fine, you should receive a response like this:\n\n```json\n{\n    \"access_token\":\"03807cb390319329bdf6c777d4dfae9c0d3b3c35\",\n    \"expires_in\":3600,\n    \"token_type\":\"bearer\",\n    \"scope\":null\n}\n```\n\n*Security note:* because this POST uses basic HTTP authentication, the\n`client_secret` is exposed in plaintext in the HTTP request. To protect this\ncall, a [TLS/SSL](http://en.wikipedia.org/wiki/Transport_Layer_Security)\nconnection is required.\n\n\n## AUTHORIZE (code)\n\nIf you have to integrate an OAuth2 service with a web application, you need to\nuse the Authorization Code grant type.  This grant requires an approval step to\nauthorize the web application. This step is implemented using a simple form that\nrequests the user approve access to the resource (account).  This module\nprovides a simple form to authorize a specific client. This form can be accessed\nby a browser using the following URL:\n\n```bash\nhttp://\u003cURL of your ZF2 app\u003e/oauth/authorize?response_type=code\u0026client_id=testclient\u0026redirect_uri=/oauth/receivecode\u0026state=xyz\n```\n\nThis page will render the form asking the user to authorize or deny the access\nfor the client. If they authorize the access, the OAuth2 module will reply with\nan Authorization code. This code must be used to request an OAuth2 token; the\nfollowing HTTPie command provides an example of how to do that:\n\n```bash\nhttp --auth testclient:testpass -f POST http://\u003cURL of your ZF2 app\u003e/oauth grant_type=authorization_code\u0026code=YOUR_CODE\u0026redirect_uri=/oauth/receivecode\n```\n\nIn client-side scenarios (i.e mobile) where you cannot store the Client\nCredentials in a secure way, you cannot use the previous workflow. In this case\nwe can use an *implicit grant*. This is similar to the authorization code, but\nrather than an authorization code being returned from the authorization request,\na *token* is returned.\n\nTo enable the module to accept the implicit grant type, you need to change the\nconfiguration of `allow_implicit` to `true` in the\n`config/autoload/oauth2.local.php` file:\n\n\n```php\nreturn array(\n    'zf-oauth2' =\u003e array(\n        // ...\n        'allow_implicit' =\u003e true,\n        // ...\n    ),\n);\n```\n\nTo request a token from the client side, you need to request authorization via\nthe OAuth2 server:\n\n```\nhttp://\u003cURL of your ZF2 app\u003e/oauth/authorize?response_type=token\u0026client_id=testclient\u0026redirect_uri=/oauth/receivecode\u0026state=xyz\n```\n\nThis request will render the authorization form as in the previous example. If\nyou authorize the access, the request will be redirected to `/oauth/receivecode`\n(as provided in the `redirect_uri` parameter in the above example), with the\n`access_token` specified in the URI fragment, per the following sample:\n\n```\n/oauth/receivecode#access_token=559d8f9b6bedd8d94c8e8d708f87475f4838c514\u0026expires_in=3600\u0026token_type=Bearer\u0026state=xyz\n```\n\nTo get the `access_token`, you can parse the URI. We used the URI fragment to\npass the `access_token` because in this way the token is not transmitted to the\nserver; it will available only to the client.\n\nIn JavaScript, you can easily parse the URI with this snippet of code:\n\n```javascript\n// function to parse fragment parameters\nvar parseQueryString = function( queryString ) {\n    var params = {}, queries, temp, i, l;\n\n    // Split into key/value pairs\n    queries = queryString.split(\"\u0026\");\n\n    // Convert the array of strings into an object\n    for ( i = 0, l = queries.length; i \u003c l; i++ ) {\n        temp = queries[i].split('=');\n        params[temp[0]] = temp[1];\n    }\n    return params;\n};\n\n// get token params from URL fragment\nvar tokenParams = parseQueryString(window.location.hash.substr(1));\n```\n\n## REVOKE (code)\n\nStarting with version 1.4.0, you can revoke access tokens. By default, revocation\nhappens via a POST request to the path `/oauth/revoke`, which expects a payload\nwith:\n\n- `token`, the OAuth2 access token to revoke.\n- `token_type_hint =\u003e 'access_token'`, indicating that an access token is being\n  revoked.\n\nThe payload may be delivered as `application/x-www-form-urlencoded` or as JSON.\n\n## Access a test resource\n\nWhen you obtain a valid token, you can access a restricted API resource. The\nOAuth2 module is shipped with a test resource that is accessible with the URL\n`/oauth/resource`. This is a simple resource that returns JSON data.\n\nTo access the test resource, you can use the following HTTPie command:\n\n```bash\nhttp -f POST http://\u003cURL of your ZF2 app\u003e/oauth/resource access_token=000ab5afab4cbbbda803fb9e50e7943f5e766748\n# or\nhttp http://\u003c\u003cURL of your ZF2 app\u003e/oauth/resource \"Authorization:Bearer 000ab5afab4cbbbda803fb9e50e7943f5e766748\"\n```\n\nAs you can see, the OAuth2 module supports the data either via POST, using the\n`access_token` value, or using the [Bearer](http://tools.ietf.org/html/rfc6750)\nauthorization header.\n\n## How to protect your API using OAuth2\n\nYou can protect your API using the following code (for instance, at the top of a\ncontroller):\n\n```php\nif (!$this-\u003eserver-\u003everifyResourceRequest(OAuth2Request::createFromGlobals())) {\n    // Not authorized return 401 error\n    $this-\u003egetResponse()-\u003esetStatusCode(401);\n    return;\n}\n```\n\nwhere `$this-\u003eserver` is an instance of `OAuth2\\Server` (see the\n[AuthController.php](src/Controller/AuthController.php)).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzfcampus%2Fzf-oauth2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzfcampus%2Fzf-oauth2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzfcampus%2Fzf-oauth2/lists"}