virgantara / unida-apps-support
A collection of UNIDA Gontor Apps Components.
Requires
- php: >=7.4
- firebase/php-jwt: ^5.2
- yiisoft/yii2: ~2.0.0
README
A reusable Yii2 component package for UNIDA Gontor applications. This package provides helper components for OAuth2 authentication, token handling, user session integration, and application jump support between UNIDA apps.
๐ฆ Features
- OAuth2 Authorization Code integration
- Access token and refresh token management
- User info retrieval from SSO server
- Allowed application list retrieval
- Secure app-to-app jump support
- Yii2 component-based integration
โ ๏ธ Security Notice
This package must use OAuth2 Authorization Code Flow for authentication and app jumping.
Do not send access_token or refresh_token through URL query parameters.
Bad example:
https://app.example.com/callback?access_token=xxx&refresh_token=yyy
Recommended flow:
Source App
โ
Target App /site/start-sso
โ
SSO /oauth/authorize
โ
Target App /site/auth-callback?code=xxx&state=yyy
โ
Target App exchanges code for token
๐ Requirements
- PHP >= 7.4
- Yii2 Framework
- Composer
- OAuth2 SSO server
โ๏ธ Installation
1. Add Repository to composer.json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/virgantara/Unida-Apps-Support.git"
}
]
}
2. Add Package Requirement
For development branch:
{
"require": {
"virgantara/unida-apps-support": "dev-master"
}
}
For stable release tag:
{
"require": {
"virgantara/unida-apps-support": "^1.0"
}
}
Then run:
composer update -vvv
Or install directly:
composer require virgantara/unida-apps-support:^1.0
๐ง OAuth Configuration
Add this configuration to params.php or params-local.php.
return [ 'oauth' => [ 'client_id' => 'your-client-id', 'client_secret' => 'your-client-secret', 'baseurl' => 'https://your-sso-server.com', 'redirectUri' => 'https://your-app.com/site/auth-callback', 'scope' => 'read write', ], ];
Example:
return [ 'oauth' => [ 'client_id' => 'elitabmas', 'client_secret' => 'your-secret', 'baseurl' => 'https://sso.unida.gontor.ac.id', 'redirectUri' => 'https://elitabmas.unida.gontor.ac.id/site/auth-callback', 'scope' => 'read write', ], ];
๐งฉ Yii2 Component Configuration
Open config/web.php, then add the components below.
'components' => [ // Other components... 'tokenService' => [ 'class' => 'virgantara\components\TokenService', ], 'aplikasi' => [ 'class' => 'virgantara\components\AplikasiAuth', 'baseurl' => $params['oauth']['baseurl'], ], 'tokenManager' => [ 'class' => 'virgantara\components\TokenManager', ], 'oauth2' => [ 'class' => 'virgantara\components\OAuth2Client', 'tokenValidationUrl' => $params['oauth']['baseurl'], 'tokenRefreshUrl' => $params['oauth']['baseurl'], 'client_id' => $params['oauth']['client_id'], 'client_secret' => $params['oauth']['client_secret'], ], ],
๐ Start SSO Login
Add this action to your SiteController.
public function actionStartSso() { $session = Yii::$app->session; if (!$session->isActive) { $session->open(); } $state = Yii::$app->security->generateRandomString(40); $session->set('oauth_state', $state); $params = [ 'client_id' => Yii::$app->params['oauth']['client_id'], 'redirect_uri' => Yii::$app->params['oauth']['redirectUri'], 'response_type' => 'code', 'scope' => Yii::$app->params['oauth']['scope'] ?? 'read write', 'state' => $state, ]; $authUrl = rtrim(Yii::$app->params['oauth']['baseurl'], '/') . '/oauth/authorize?' . http_build_query($params); return $this->redirect($authUrl); }
๐ OAuth Callback
Add this callback action to your SiteController.
public function actionAuthCallback() { try { $session = Yii::$app->session; if (!$session->isActive) { $session->open(); } $sessionState = $session->get('oauth_state'); $receivedState = Yii::$app->request->get('state'); if (empty($sessionState) || empty($receivedState) || $sessionState !== $receivedState) { throw new \yii\web\BadRequestHttpException('Invalid OAuth state.'); } $authCode = Yii::$app->request->get('code'); if (empty($authCode)) { throw new \yii\web\BadRequestHttpException('Authorization code not received.'); } $response = Yii::$app->tokenManager->fetchAccessTokenWithAuthCode($authCode); if (empty($response['access_token'])) { throw new \yii\web\UnauthorizedHttpException('Failed to get access token.'); } $accessToken = $response['access_token']; $refreshToken = $response['refresh_token'] ?? null; $userinfo = Yii::$app->tokenManager->getUserinfo($accessToken); if (empty($userinfo) || empty($userinfo['email'])) { throw new \yii\web\UnauthorizedHttpException('Failed to get user info.'); } $session->set('access_token', $accessToken); if (!empty($refreshToken)) { $session->set('refresh_token', $refreshToken); } /* * TODO: * Implement local user login here. * * Example: * - Find local user by email * - Create user if allowed * - Login using Yii::$app->user->login($identity) */ return $this->redirect(['site/index']); } catch (\Throwable $e) { return $this->handleException($e); } }
Add the exception handler:
protected function handleException($e) { Yii::error($e->getMessage(), __METHOD__); Yii::$app->session->setFlash('danger', $e->getMessage()); return $this->redirect(['site/index']); }
๐งญ App-to-App Jump
This package supports Google-like app jumping.
Example:
SIAKAD โ ELITABMAS
E-KHIDMAH โ MOODLE
MOODLE โ SIAKAD
The source app should only open the target app login endpoint:
https://target-app.unida.gontor.ac.id/site/start-sso
The target app will then start its own OAuth2 flow.
Correct flow:
User is logged in to SIAKAD
โ
User clicks ELITABMAS
โ
Browser opens ELITABMAS /site/start-sso
โ
ELITABMAS redirects to SSO /oauth/authorize
โ
SSO detects active SSO session
โ
SSO redirects back to ELITABMAS callback with authorization code
โ
ELITABMAS exchanges code for token
โ
User is logged in to ELITABMAS
The source application must not generate OAuth state for the target application.
๐ฑ Allowed Apps List
You can render allowed applications from SSO using:
$apps = Yii::$app->aplikasi->getRenderedAllowedAppsList();
Example usage in layout or menu:
use yii\widgets\Menu; echo Menu::widget([ 'items' => Yii::$app->aplikasi->getRenderedAllowedAppsList(), 'encodeLabels' => false, ]);
The SSO /app/list endpoint should return data like this:
[
{
"app_id": 1,
"client_id": "siakad",
"app_name": "SIAKAD",
"base_url": "https://siakad.unida.gontor.ac.id",
"jump_callback": "/site/start-sso"
},
{
"app_id": 2,
"client_id": "elitabmas",
"app_name": "ELITABMAS",
"base_url": "https://elitabmas.unida.gontor.ac.id",
"jump_callback": "/site/start-sso"
}
]
Or preferably:
[
{
"app_id": 2,
"client_id": "elitabmas",
"app_name": "ELITABMAS",
"start_sso_url": "https://elitabmas.unida.gontor.ac.id/site/start-sso"
}
]
๐ช Logout
Recommended logout flow:
Application logout
โ
Clear local Yii2 session
โ
Redirect to SSO logout endpoint
โ
SSO clears global SSO session
โ
Redirect back to application logout callback
Example:
public function actionLogout() { Yii::$app->user->logout(); Yii::$app->session->remove('access_token'); Yii::$app->session->remove('refresh_token'); $logoutUrl = rtrim(Yii::$app->params['oauth']['baseurl'], '/') . '/oauth/logout?' . http_build_query([ 'client_id' => Yii::$app->params['oauth']['client_id'], ]); return $this->redirect($logoutUrl); }
๐ท๏ธ Release Tag Procedure
Use semantic versioning for releases.
Format:
MAJOR.MINOR.PATCH
Examples:
v1.0.0
v1.0.1
v1.1.0
v2.0.0
1. Check Current Branch
git branch
Switch to master or main branch:
git checkout master
or:
git checkout main
2. Pull Latest Changes
git pull origin master
or:
git pull origin main
3. Check Git Status
git status
Make sure there are no uncommitted changes.
4. Commit Changes
git add . git commit -m "Prepare release v1.0.0"
Skip this step if all changes have already been committed.
5. Create Git Tag
git tag -a v1.0.0 -m "Release v1.0.0"
6. Push Commit and Tag
If using master:
git push origin master git push origin v1.0.0
If using main:
git push origin main git push origin v1.0.0
Or push all tags:
git push origin --tags
7. Verify Tag
git tag
Or check remote tags:
git ls-remote --tags origin
๐ฆ Using a Release Tag in Yii2 App
After creating a release tag, update the Yii2 app composer.json.
{
"require": {
"virgantara/unida-apps-support": "^1.0"
}
}
Then run:
composer update virgantara/unida-apps-support -vvv
For a specific version:
{
"require": {
"virgantara/unida-apps-support": "1.0.0"
}
}
Then:
composer update virgantara/unida-apps-support -vvv
๐ Updating Release Version
For bug fixes:
git tag -a v1.0.1 -m "Release v1.0.1"
git push origin v1.0.1
For new backward-compatible features:
git tag -a v1.1.0 -m "Release v1.1.0"
git push origin v1.1.0
For breaking changes:
git tag -a v2.0.0 -m "Release v2.0.0"
git push origin v2.0.0
๐งน Removing a Wrong Tag
Remove local tag:
git tag -d v1.0.0
Remove remote tag:
git push origin --delete v1.0.0
Create the corrected tag again:
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
๐งช Testing Package Installation Locally
In a Yii2 application:
composer clear-cache composer update virgantara/unida-apps-support -vvv
Check installed version:
composer show virgantara/unida-apps-support
๐ Suggested Package Structure
Unida-Apps-Support/
โโโ composer.json
โโโ README.md
โโโ src/
โ โโโ components/
โ โโโ AplikasiAuth.php
โ โโโ OAuth2Client.php
โ โโโ TokenManager.php
โ โโโ TokenService.php
โโโ LICENSE
๐งพ Example Package composer.json
{
"name": "virgantara/unida-apps-support",
"description": "Support components for Yii2 UNIDA Gontor applications",
"type": "yii2-extension",
"license": "MIT",
"authors": [
{
"name": "Oddy Virgantara Putra",
"email": "your-email@example.com"
}
],
"require": {
"php": ">=7.4",
"yiisoft/yii2": "~2.0.0",
"yiisoft/yii2-httpclient": "*",
"firebase/php-jwt": "^6.0"
},
"autoload": {
"psr-4": {
"virgantara\\": "src/"
}
}
}
If your component files are placed directly under:
components/
then use:
{
"autoload": {
"psr-4": {
"virgantara\\": ""
}
}
}
โ Recommended Release Checklist
Before creating a new tag:
- Code is committed
-
composer.jsonis valid - Namespace matches PSR-4 autoload
- README is updated
- No token is exposed through URL
- OAuth callback uses authorization code
- App jump uses target app
/site/start-sso - Version tag is created
- Tag is pushed to GitHub
- Yii2 app can install the tagged version
๐ License
This package is open-sourced under the MIT license.