PHPackages                             dmstr/yii2-usuario-keycloak - 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. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. dmstr/yii2-usuario-keycloak

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

dmstr/yii2-usuario-keycloak
===========================

Yii2 usuario keycloak plugin

5.1.1(3w ago)314.0k↑43.6%2PHP

Since Jan 13Pushed 1mo ago4 watchersCompare

[ Source](https://github.com/dmstr/yii2-usuario-keycloak)[ Packagist](https://packagist.org/packages/dmstr/yii2-usuario-keycloak)[ RSS](/packages/dmstr-yii2-usuario-keycloak/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (10)Dependencies (36)Versions (52)Used By (0)

Yii2 usuario keycloak client
============================

[](#yii2-usuario-keycloak-client)

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

[](#installation)

Install the package via composer

```
composer require dmstr/yii2-usuario-keycloak
```

For the installation of usuario see [usuario docs](https://yii2-usuario.readthedocs.io/en/latest/)

Setup
-----

[](#setup)

To run a keycloak using Docker (compose) please see [docker-compose.keycloak.yml](docker/docker-compose.keycloak.yml) in the docker folder

For local development you should add keycloak-local to your /etc/hosts like this: 127.0.0.1 keycloak-local

You may need to replace 127.0.0.1 with your docker ip

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

[](#configuration)

**This part of config is mandatory. With this we add keycloak as a "social network"**

```
KEYCLOAK_CLIENT_NAME=Keycloak
KEYCLOAK_CLIENT_ID=app
# See credentials tab in example realms app client
KEYCLOAK_CLIENT_SECRET=
KEYCLOAK_ISSUER_URL=http://keycloak-local:8080/realms/example
```

```
use yii\authclient\Collection;
use Da\User\AuthClient\Keycloak;

return [
    'components' => [
        'authClientCollection' => [
            'class' => Collection::class,
            'clients' => [
                'keycloak' => [
                    'class' => Keycloak::class,
                    'title' => getenv('KEYCLOAK_CLIENT_NAME'),
                    'clientId' => getenv('KEYCLOAK_CLIENT_ID'),
                    'clientSecret' => getenv('KEYCLOAK_CLIENT_SECRET'),
                    'issuerUrl' => getenv('KEYCLOAK_ISSUER_URL')
                ]
            ]
        ],
        'user' => [
            // So that the session do not get mixed up
            'enableAutoLogin' => false
        ]
    ]
]
```

**Enable front channel logout from keycloak when user logs out in app**

```
use dmstr\usuario\keycloak\controllers\SecurityController;

return [
    'modules' => [
        'user' => [
            'controllerMap' => [
                'security' => [
                    'class' => SecurityController::class
                ]
            ]
        ]
    ]
]
```

Social login mode (SSO connect hardening)
-----------------------------------------

[](#social-login-mode-sso-connect-hardening)

When a Keycloak login callback arrives while a **local session already exists**, the base `2amigos/yii2-usuario` behaviour treats it as *"connect the returned identity to the current session"*. That is correct for classic interactive account-linking (a logged-in user clicks *"connect Google"* in their profile), but wrong for pure SSO deployments where the **same**`security/auth` endpoint is the primary login: a stale session then captures whatever identity the callback returns — binding the **wrong** person's Keycloak `sub` to the open account.

`SecurityController::$socialLoginMode` controls this. The default is **`legacy`** so existing installations are unaffected; SSO deployments should opt in to `guarded`.

ModeGuest loginLogin while a session is openUse for`legacy` *(default)*authenticate**connect** returned identity to the open session (no identity check)non-SSO / classic account-linking; backwards-compatible default`guarded` *(recommended for SSO)*authenticateconnect **only** if the returned identity provably belongs to the same user (owner resolved by immutable `sub`, else by verified e-mail); otherwise log out the stale session and authenticate as the true identitypure Keycloak SSO where the auth endpoint is the primary login`authenticate`authenticatealways authenticate via the token identity; never connect-to-sessionSSO where profile-based account-linking is never used```
use dmstr\usuario\keycloak\controllers\SecurityController;

return [
    'modules' => [
        'user' => [
            'controllerMap' => [
                'security' => [
                    'class' => SecurityController::class,
                    // opt in to SSO connect hardening
                    'socialLoginMode' => SecurityController::SOCIAL_LOGIN_MODE_GUARDED,
                ]
            ]
        ]
    ]
]
```

Notes:

- **Unknown values fail fast.** An invalid `socialLoginMode` (e.g. a typo) throws `InvalidConfigException` in `init()` — it never silently falls back to `legacy`, so a consumer that meant to opt in to hardening cannot end up unprotected by accident.
- **`email_verified` is enforced strictly** in `guarded`: a *missing* `email_verified` claim counts as **not** verified. This is deliberately stricter than the app-side event handler pattern below (`isset(...) && === false`, which lets a missing claim through).
- **`guarded` populates `email`/`username`** on the account row (unlike the base connect path), so it produces no new rows with empty columns.
- **Pre-existing mislinks are perpetuated, not repaired.** Under `guarded` the owner is resolved from the current DB state, so an already-wrong `sub → user` link keeps logging in the wrong user until the data is cleaned. Deploy the code fix **first**, then run the data cleanup.
- **`guarded` cannot tell an SSO login from an intentional profile connect**, because both run through the same `security/auth` endpoint. If a deployment relies on users deliberately linking a second identity with a *different* verified e-mail, `guarded` will block that. Evaluate before enabling.
- **Planned change:** the default is expected to flip to `guarded` in **6.0.0**.

**Only allow login to users with verified emails**

```
use Da\User\Event\SocialNetworkAuthEvent;
use dmstr\usuario\keycloak\controllers\SecurityController;
use yii\web\ForbiddenHttpException;

return [
    'modules' => [
        'user' => [
            'controllerMap' => [
                'security' => [
                    'class' => SecurityController::class,
                    'on ' . SocialNetworkAuthEvent::EVENT_BEFORE_AUTHENTICATE => function (SocialNetworkAuthEvent $event) {
                        if (isset($event->getClient()->getUserAttributes()['email_verified']) && $event->getClient()->getUserAttributes()['email_verified'] === false) {
                            throw new ForbiddenHttpException(Yii::t('usuario-keycloak', 'Account is not verified. Please confirm your registration email.'));
                        }
                    }
                ]
            ]
        ]
    ]
]
```

**Disabled the sending of a welcome message when a user is from keycloak**

```
return [
    'modules' => [
        'user' => [
            'sendWelcomeMailAfterSocialNetworkRegistration' => false
        ]
    ]
]
```

**If you do not want to allow identity switching. This is recommended because potential RBAC Roles with the TokenRoleRule may not work correctly**

```
return [
    'modules' => [
        'user' => [
            'enableSwitchIdentities' => false
        ]
    ]
]
```

**Logout the user if the keycloak token is expired**

This only works in a web application so add your config accordingl and needs some slight modifications to your user component. You can copy and use this example or extend your existing user compoent.

```
