PHPackages                             laminas-api-tools/api-tools-oauth2 - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. laminas-api-tools/api-tools-oauth2

ActiveLibrary[Framework](/categories/framework)

laminas-api-tools/api-tools-oauth2
==================================

Laminas module for implementing an OAuth2 server

1.9.0(2y ago)112.0M—3.1%22[11 issues](https://github.com/laminas-api-tools/api-tools-oauth2/issues)[2 PRs](https://github.com/laminas-api-tools/api-tools-oauth2/pulls)5BSD-3-ClausePHPPHP ~8.0.0 || ~8.1.0 || ~8.2.0CI passing

Since Dec 31Pushed 3mo ago11 watchersCompare

[ Source](https://github.com/laminas-api-tools/api-tools-oauth2)[ Packagist](https://packagist.org/packages/laminas-api-tools/api-tools-oauth2)[ Docs](https://api-tools.getlaminas.org)[ Fund](https://funding.communitybridge.org/projects/laminas-project)[ RSS](/packages/laminas-api-tools-api-tools-oauth2/feed)WikiDiscussions 1.10.x Synced 1mo ago

READMEChangelog (8)Dependencies (22)Versions (77)Used By (5)

api-tools-oauth2
================

[](#api-tools-oauth2)

[![Build Status](https://github.com/laminas-api-tools/api-tools-oauth2/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/laminas-api-tools/api-tools-oauth2/actions/workflows/continuous-integration.yml)

> ## 🇷🇺 Русским гражданам
>
> [](#-русским-гражданам)
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> [](#-to-citizens-of-russia)
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"

Laminas module for [OAuth2](http://oauth.net/2/) authentication.

This module uses the [oauth2-server-php](https://github.com/bshaffer/oauth2-server-php)library by Brent Shaffer to provide OAuth2 support.

Requirements
------------

[](#requirements)

Please see the [composer.json](composer.json) file.

Installation
------------

[](#installation)

You can install using:

```
$ composer require laminas-api-tools/api-tools-oauth2
```

If you are using ext/mongodb, you will also need to install a compatibility package:

```
$ composer require alcaeus/mongo-php-adapter
```

Finally, you will need to add the following modules to your application's configuration:

```
'modules' => [
    /* ... */
    'Laminas\ApiTools\ApiProblem',
    'Laminas\ApiTools\ContentNegotiation',
    'Laminas\ApiTools\OAuth2',
],
```

> ### laminas-component-installer
>
> [](#laminas-component-installer)
>
> If you use [laminas-component-installer](https://github.com/laminas/laminas-component-installer), that plugin will install api-tools-oauth2 and its other Laminas API Tools dependencies as modules for you.

Configuration
-------------

[](#configuration)

This module uses any PDO-suported database to manage the OAuth2 information (users, client, token, etc). The database structure is stored in `data/db_oauth2.sql`.

```
CREATE TABLE oauth_clients (
    client_id VARCHAR(80) NOT NULL,
    client_secret VARCHAR(80) NOT NULL,
    redirect_uri VARCHAR(2000) NOT NULL,
    grant_types VARCHAR(80),
    scope VARCHAR(2000),
    user_id VARCHAR(255),
    CONSTRAINT clients_client_id_pk PRIMARY KEY (client_id)
);
CREATE TABLE oauth_access_tokens (
    access_token VARCHAR(40) NOT NULL,
    client_id VARCHAR(80) NOT NULL,
    user_id VARCHAR(255),
    expires TIMESTAMP NOT NULL,
    scope VARCHAR(2000),
    CONSTRAINT access_token_pk PRIMARY KEY (access_token)
);
CREATE TABLE oauth_authorization_codes (
    authorization_code VARCHAR(40) NOT NULL,
    client_id VARCHAR(80) NOT NULL,
    user_id VARCHAR(255),
    redirect_uri VARCHAR(2000),
    expires TIMESTAMP NOT NULL,
    scope VARCHAR(2000),
    id_token VARCHAR(2000),
    CONSTRAINT auth_code_pk PRIMARY KEY (authorization_code)
);
CREATE TABLE oauth_refresh_tokens (
    refresh_token VARCHAR(40) NOT NULL,
    client_id VARCHAR(80) NOT NULL,
    user_id VARCHAR(255),
    expires TIMESTAMP NOT NULL,
    scope VARCHAR(2000),
    CONSTRAINT refresh_token_pk PRIMARY KEY (refresh_token)
);
CREATE TABLE oauth_users (
    username VARCHAR(255) NOT NULL,
    password VARCHAR(2000),
    first_name VARCHAR(255),
    last_name VARCHAR(255),
    CONSTRAINT username_pk PRIMARY KEY (username)
);
CREATE TABLE oauth_scopes (
    type VARCHAR(255) NOT NULL DEFAULT "supported",
    scope VARCHAR(2000),
    client_id VARCHAR (80),
    is_default SMALLINT DEFAULT NULL
);
CREATE TABLE oauth_jwt (
    client_id VARCHAR(80) NOT NULL,
    subject VARCHAR(80),
    public_key VARCHAR(2000),
    CONSTRAINT jwt_client_id_pk PRIMARY KEY (client_id)
);
```

> ### PostgreSQL
>
> [](#postgresql)
>
> We also have a PostgreSQL-specific DDL in `data/db_oauth2_postgresql.sql`.

For security reasons, we encrypt the fields `client_secret` (table `oauth_clients`) and `password` (table `oauth_users`) using the [bcrypt](http://en.wikipedia.org/wiki/Bcrypt) algorithm (via the class [Laminas\\Crypt\\Password\\Bcrypt](https://getlaminas.org/manual/2.2/en/modules/laminas.crypt.password.html#bcrypt)).

In order to configure the api-tools-oauth2 module for database access, you need to copy the file `config/oauth2.local.php.dist` to `config/autoload/oauth2.local.php` in your Laminas application, and edit it to provide your DB credentials (DNS, username, password).

We also include a SQLite database in `data/dbtest.sqlite` that you can use in a test environment. In this database, you will find a test client account with the `client_id` "testclient" and the `client_secret` "testpass". If you want to use this database, you can configure your `config/autoload/oauth2.local.php`file as follow:

```
return array(
    'api-tools-oauth2' => array(
        'db' => array(
            'dsn' => 'sqlite:/data/dbtest.sqlite',
        ),
    ),
);
```

Mongo Configuration
-------------------

[](#mongo-configuration)

The Mongo OAuth2 adapter wraps the bshaffer adapter by adding the same password encryption as the rest of api-tools. The collections needed are the same as above in the PDO adapter. To create an OAuth2 client, insert a document like the following into the oauth\_clients collection:

```
{
    "client_id":     "testclient",
    "client_secret": "$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2",
    "redirect_uri":  "/oauth/receivecode",
    "grant_types":   null
}
```

User ID Provider
----------------

[](#user-id-provider)

When a user requests an authorization code they may provide their user\_id as a request parameter to the `/oauth/authorize` route. This will store the `user_id` in the `access_token`, `refresh_token`, and `authorization_code` tables as the user goes throught the oauth2 process.

A user may be authenticated through `Laminas\Authentication\AuthenticationService` or another authentication means. When a user must provide authentication before they may access the `/oauth/authorize` route, the authenticated user ID should be used. This is done with the service manager alias `Laminas\ApiTools\OAuth2\Provider\UserId`.

The default User ID Provider uses the request query parameter `user_id` and is handled via the class `Laminas\ApiTools\OAuth2\Provider\UserId\Request`.

Provided with this repository is an alternative provider, `Laminas\ApiTools\OAuth2\Provider\UserId\AuthorizationService`, which uses `Laminas\Authentication\AuthenticationService` to fetch the identity. To change the User ID Provider to use this service, change the `Laminas\ApiTools\OAuth2\Provider\UserId` service alias to point at it:

```
return array(
    'service_manager' =>
        'aliases' => array(
            'Laminas\ApiTools\OAuth2\Provider\UserId' => 'Laminas\ApiTools\OAuth2\Provider\UserId\AuthenticationService',
        ),
    ),
);
```

How to test OAuth2
------------------

[](#how-to-test-oauth2)

To test the OAuth2 module, you have to add a `client_id` and a `client_secret`into the oauth2 database. If you are using the SQLite test database, you don't need to add a `client_id`; just use the default "testclient"/"testpass" account.

Because we encrypt the password using the `bcrypt` algorithm, you need to encrypt the password using the [Laminas\\Crypt\\Password\\Bcrypt](https://getlaminas.org/manual/2.2/en/modules/laminas.crypt.password.html#bcrypt)class from Laminas. We provided a simple script in `/bin/bcrypt.php` to generate the hash value of a user's password. You can use this tool from the command line, with the following syntax:

```
php bin/bcrypt.php testpass
```

where "testpass" is the user's password that you want to encrypt. The output of the previous command will be the hash value of the user's password, a string of 60 bytes like the following:

```
$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2

```

After the generation of the hash value of the password (`client_secret`), you can add a new `client_id` in the database using the following SQL statement:

```
INSERT INTO oauth_clients (
    client_id,
    client_secret,
    redirect_uri)
VALUES (
    "testclient",
    "$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2",
    "/oauth/receivecode"
);
```

To test the OAuth2 module, you can use an HTTP client like [HTTPie](https://github.com/jkbr/httpie) or [CURL](http://curl.haxx.se/). The examples below use HTTPie and the test account "testclient"/"testpass".

REQUEST TOKEN (client\_credentials)
-----------------------------------

[](#request-token-client_credentials)

You can request an OAuth2 token using the following HTTPie command:

```
http --auth testclient:testpass -f POST http:///oauth grant_type=client_credentials
```

This POST requests a new token to the OAuth2 server using the *client\_credentials*mode. This is typical in machine-to-machine interaction for application access. If everything works fine, you should receive a response like this:

```
{
    "access_token":"03807cb390319329bdf6c777d4dfae9c0d3b3c35",
    "expires_in":3600,
    "token_type":"bearer",
    "scope":null
}
```

*Security note:* because this POST uses basic HTTP authentication, the `client_secret` is exposed in plaintext in the HTTP request. To protect this call, a [TLS/SSL](http://en.wikipedia.org/wiki/Transport_Layer_Security)connection is required.

AUTHORIZE (code)
----------------

[](#authorize-code)

If you have to integrate an OAuth2 service with a web application, you need to use the Authorization Code grant type. This grant requires an approval step to authorize the web application. This step is implemented using a simple form that requests the user approve access to the resource (account). This module provides a simple form to authorize a specific client. This form can be accessed by a browser using the following URL:

```
http:///oauth/authorize?response_type=code&client_id=testclient&redirect_uri=/oauth/receivecode&state=xyz
```

This page will render the form asking the user to authorize or deny the access for the client. If they authorize the access, the OAuth2 module will reply with an Authorization code. This code must be used to request an OAuth2 token; the following HTTPie command provides an example of how to do that:

```
http --auth testclient:testpass -f POST http:///oauth grant_type=authorization_code&code=YOUR_CODE&redirect_uri=/oauth/receivecode
```

In client-side scenarios (i.e mobile) where you cannot store the Client Credentials in a secure way, you cannot use the previous workflow. In this case we can use an *implicit grant*. This is similar to the authorization code, but rather than an authorization code being returned from the authorization request, a *token* is returned.

To enable the module to accept the implicit grant type, you need to change the configuration of `allow_implicit` to `true` in the `config/autoload/oauth2.local.php` file:

```
return array(
    'api-tools-oauth2' => array(
        // ...
        'allow_implicit' => true,
        // ...
    ),
);
```

To request a token from the client side, you need to request authorization via the OAuth2 server:

```
http:///oauth/authorize?response_type=token&client_id=testclient&redirect_uri=/oauth/receivecode&state=xyz

```

This request will render the authorization form as in the previous example. If you authorize the access, the request will be redirected to `/oauth/receivecode`(as provided in the `redirect_uri` parameter in the above example), with the `access_token` specified in the URI fragment, per the following sample:

```
/oauth/receivecode#access_token=559d8f9b6bedd8d94c8e8d708f87475f4838c514&expires_in=3600&token_type=Bearer&state=xyz

```

To get the `access_token`, you can parse the URI. We used the URI fragment to pass the `access_token` because in this way the token is not transmitted to the server; it will available only to the client.

In JavaScript, you can easily parse the URI with this snippet of code:

```
// function to parse fragment parameters
var parseQueryString = function( queryString ) {
    var params = {}, queries, temp, i, l;

    // Split into key/value pairs
    queries = queryString.split("&");

    // Convert the array of strings into an object
    for ( i = 0, l = queries.length; i  'access_token'`, indicating that an access token is being revoked.

The payload may be delivered as `application/x-www-form-urlencoded` or as JSON.

Access a test resource
----------------------

[](#access-a-test-resource)

When you obtain a valid token, you can access a restricted API resource. The OAuth2 module is shipped with a test resource that is accessible with the URL `/oauth/resource`. This is a simple resource that returns JSON data.

To access the test resource, you can use the following HTTPie command:

```
http -f POST http:///oauth/resource access_token=000ab5afab4cbbbda803fb9e50e7943f5e766748
# or
http http://server->verifyResourceRequest(OAuth2Request::createFromGlobals())) {
    // Not authorized return 401 error
    $this->getResponse()->setStatusCode(401);
    return;
}
```

where `$this->server` is an instance of `OAuth2\Server` (see the [AuthController.php](src/Controller/AuthController.php)).

###  Health Score

54

—

FairBetter than 97% of packages

Maintenance33

Infrequent updates — may be unmaintained

Popularity51

Moderate usage in the ecosystem

Community36

Small or concentrated contributor base

Maturity85

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 69.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~17 days

Recently: every ~101 days

Total

76

Last Release

1042d ago

Major Versions

0.9.0 → 1.0.02019-12-31

0.9.1p1 → 1.0.0p12020-01-07

0.9.1p2 → 1.0.0p22020-03-23

PHP version history (8 changes)0.7.0PHP &gt;=5.4.9

0.8.0PHP &gt;=5.4.8

0.9.1PHP &gt;=5.3.23

1.3.0PHP &gt;=5.5

1.4.0PHP ^5.6 || ^7.0

1.7.0PHP ^7.3 || ~8.0.0

1.8.x-devPHP ^7.4 || ~8.0.0 || ~8.1.0

1.10.x-devPHP ~8.0.0 || ~8.1.0 || ~8.2.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/25943?v=4)[Matthew Weier O'Phinney](/maintainers/weierophinney)[@weierophinney](https://github.com/weierophinney)

![](https://avatars.githubusercontent.com/u/296074?v=4)[Zend Framework](/maintainers/zendframework)[@zendframework](https://github.com/zendframework)

---

Top Contributors

[![weierophinney](https://avatars.githubusercontent.com/u/25943?v=4)](https://github.com/weierophinney "weierophinney (351 commits)")[![michalbundyra](https://avatars.githubusercontent.com/u/7423207?v=4)](https://github.com/michalbundyra "michalbundyra (36 commits)")[![ezimuel](https://avatars.githubusercontent.com/u/475967?v=4)](https://github.com/ezimuel "ezimuel (34 commits)")[![manchuck](https://avatars.githubusercontent.com/u/192776?v=4)](https://github.com/manchuck "manchuck (10 commits)")[![jguittard](https://avatars.githubusercontent.com/u/5320213?v=4)](https://github.com/jguittard "jguittard (10 commits)")[![alanseiden](https://avatars.githubusercontent.com/u/5905791?v=4)](https://github.com/alanseiden "alanseiden (8 commits)")[![laminas-bot](https://avatars.githubusercontent.com/u/68250880?v=4)](https://github.com/laminas-bot "laminas-bot (7 commits)")[![exptom](https://avatars.githubusercontent.com/u/4302032?v=4)](https://github.com/exptom "exptom (5 commits)")[![TomHAnderson](https://avatars.githubusercontent.com/u/493920?v=4)](https://github.com/TomHAnderson "TomHAnderson (4 commits)")[![alexdenvir](https://avatars.githubusercontent.com/u/1412074?v=4)](https://github.com/alexdenvir "alexdenvir (4 commits)")[![brettmc](https://avatars.githubusercontent.com/u/4978962?v=4)](https://github.com/brettmc "brettmc (3 commits)")[![alfaproject](https://avatars.githubusercontent.com/u/60164?v=4)](https://github.com/alfaproject "alfaproject (3 commits)")[![dorongutman](https://avatars.githubusercontent.com/u/719298?v=4)](https://github.com/dorongutman "dorongutman (3 commits)")[![nclundsten](https://avatars.githubusercontent.com/u/239653?v=4)](https://github.com/nclundsten "nclundsten (3 commits)")[![Ocramius](https://avatars.githubusercontent.com/u/154256?v=4)](https://github.com/Ocramius "Ocramius (2 commits)")[![basz](https://avatars.githubusercontent.com/u/143068?v=4)](https://github.com/basz "basz (2 commits)")[![gartner](https://avatars.githubusercontent.com/u/195601?v=4)](https://github.com/gartner "gartner (2 commits)")[![ojhaujjwal](https://avatars.githubusercontent.com/u/4995501?v=4)](https://github.com/ojhaujjwal "ojhaujjwal (2 commits)")[![samsonasik](https://avatars.githubusercontent.com/u/459648?v=4)](https://github.com/samsonasik "samsonasik (2 commits)")[![lorenzoferrarajr](https://avatars.githubusercontent.com/u/1518144?v=4)](https://github.com/lorenzoferrarajr "lorenzoferrarajr (1 commits)")

---

Tags

hacktoberfestapiframeworklaminasoauth2api-tools

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/laminas-api-tools-api-tools-oauth2/health.svg)

```
[![Health](https://phpackages.com/badges/laminas-api-tools-api-tools-oauth2/health.svg)](https://phpackages.com/packages/laminas-api-tools-api-tools-oauth2)
```

###  Alternatives

[laminas-api-tools/api-tools-admin

Laminas API Tools Admin module

13794.3k5](/packages/laminas-api-tools-api-tools-admin)[laminas-api-tools/api-tools

Laminas API Tools module for Laminas

371.7M10](/packages/laminas-api-tools-api-tools)[laminas-api-tools/api-tools-skeleton

Skeleton Application for Laminas API Tools

5520.7k](/packages/laminas-api-tools-api-tools-skeleton)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
