Skip to content

Commit 75072a7

Browse files
committed
0 parents  commit 75072a7

28 files changed

+2264
-0
lines changed

.editorconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
indent_size = 4
7+
indent_style = space
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*.{yml,yaml}]
15+
indent_size = 2
16+
17+
[*.json]
18+
indent_size = 2

.gitattributes

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Path-based git attributes
2+
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
3+
4+
# Ignore all test and documentation with "export-ignore".
5+
/.editorconfig export-ignore
6+
/.github export-ignore
7+
/.gitattributes export-ignore
8+
/.gitignore export-ignore
9+
/.lando.yml export-ignore
10+
/phpunit.xml export-ignore
11+
/pint.json export-ignore
12+
/tests export-ignore

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/.phpunit.cache
2+
/.phpunit.result.cache
3+
/.idea
4+
/.vscode
5+
*.local.*
6+
/composer.lock
7+
/vendor

README.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# CUAuth
2+
3+
Middleware for authorizing Laravel users.
4+
5+
- [CUAuth SSO](#cuauth) - Single sign-on and authorization middleware
6+
- SAML PHP Toolkit integration
7+
- Apache mod_shib integration
8+
- [AppTesters](#apptesters) - Limit access to users in the `APP_TESTERS` environment variable
9+
- [Local Login](#local-login) - Allow Laravel users to log in with a local username and password
10+
11+
## Use Cases
12+
13+
- **Single Sign-On**: Protect routes with SSO (mod_shib or PHP SAML)
14+
- Optionally log in SSO users to app user accounts
15+
- **AppTesters**: Limit access on non-production sites to users in the `APP_TESTERS` environment variable
16+
17+
18+
## Single Sign-On
19+
20+
### Usage
21+
22+
```php
23+
// File: routes/web.php
24+
use CornellCustomDev\LaravelStarterKit\CUAuth\Middleware\CUAuth;
25+
26+
Route::group(['middleware' => [CUAuth::class]], function () {
27+
// Protected routes here
28+
Route::get('profile', [UserController::class, 'show']);
29+
});
30+
```
31+
32+
```dotenv
33+
# File: .env
34+
# apache-shib (default) | php-saml
35+
CU_AUTH_IDENTITY_MANAGER=apache-shib
36+
```
37+
38+
See [Authorization](#identity-and-authorization) for details on how to log in remote users for local authorization.
39+
40+
> _See also: [shibboleth configuration](SHIBBOLETH.md)._
41+
42+
---
43+
44+
### Routing
45+
46+
Any pages protected by middleware are automatically redirected to SSO. To directly trigger log in or log out, use the following routes (parameters are optional and will default to `'/'`):
47+
- Login: `route('cu-auth.sso-login', ['redirect_url' => '/home'])`
48+
- Logout: `route('cu-auth.sso-logout', ['return' => '/'])`
49+
50+
### Certs and Metadata (php-saml)
51+
52+
For using the PHP SAML Toolkit, the SAML keys and certs can be generated with the following command, or as an option from the starter kit installer:
53+
54+
```bash
55+
php artisan cu-auth:generate-keys
56+
```
57+
58+
The SAML metadata can be retrieved at `https://<site-url>/sso/metadata`.
59+
60+
The default location for the SAML keys and certs is in `storage/app/keys`. This location is configurable in the `config/cu-auth.php` file or by setting the `SAML_CERT_PATH` in `.env`.
61+
62+
---
63+
64+
### Local Testing (apache-shib)
65+
For local testing where mod_shib is not available, the `REMOTE_USER` environment variable can be set to simulate
66+
Shibboleth authentication. Note that `APP_ENV` must be set to "local" for this to work and the config cache must be cleared when `REMOTE_USER` is changed.
67+
68+
```dotenv
69+
# File: .env
70+
APP_ENV=local
71+
REMOTE_USER=abc123
72+
```
73+
74+
## Identity and Authorization
75+
76+
Once authenticated via SSO, the user's identity is available via the `IdentityManager`, which can be accessed via the app container.
77+
78+
```php
79+
use CornellCustomDev\LaravelStarterKit\CUAuth\Managers\IdentityManager;
80+
81+
$remoteIdentity = app(IdentityManager::class)->getIdentity();
82+
$netid = $remoteIdentity->id(); // NetID | CWID
83+
84+
// If provided with SSO attributes:
85+
$email = $remoteIdentity->email(); // Primary email (i.e. [email protected])
86+
$name = $remoteIdentity->name(); // Display name
87+
```
88+
89+
### User authorization
90+
91+
If the site should manage authorization for users in the application, set `config('cu-auth.require_local_user')` to true:
92+
93+
```php
94+
# File: config/cu-auth.php
95+
'require_local_user' => env('REQUIRE_LOCAL_USER', true),
96+
```
97+
98+
Requiring a local user triggers the `CUAuthenticated` event when a user is authenticated via single sign-on. The site must
99+
[register a listener](https://laravel.com/docs/11.x/events#registering-events-and-listeners) for
100+
the `CUAuthenticated` event. This listener should look up the user in the database and log them in or create a user
101+
as needed.
102+
103+
> [AuthorizeUser](Listeners/AuthorizeUser.php) is provided as a starting point for handling the CUAuthenticated event.
104+
> It is simplistic and should be replaced with a site-specific implementation in the site code base. It demonstrates
105+
> retrieving user data via the [IdentityManager](Managers/IdentityManager.php) and creating a user if they do not exist.
106+
107+
108+
## Configuration
109+
110+
See [config/cu-auth.php](../../config/cu-auth.php) for configuration options, all of which can be set with environment variables.
111+
112+
To modify the default configuration, publish the configuration file:
113+
114+
```bash
115+
php artisan vendor:publish --tag=starterkit:cu-auth-config
116+
```
117+
118+
To modify the PHP SAML Toolkit configuration, publish the configuration file:
119+
120+
```bash
121+
php artisan vendor:publish --tag=starterkit:php-saml-toolkit-config
122+
```
123+
124+
125+
## AppTesters
126+
127+
Limits non-production access to users in the `APP_TESTERS` environment variable.
128+
129+
### Usage
130+
131+
```php
132+
// File: routes/web.php
133+
use CornellCustomDev\LaravelStarterKit\CUAuth\Middleware\AppTesters;
134+
use CornellCustomDev\LaravelStarterKit\CUAuth\Middleware\CUAuth;
135+
136+
Route::group(['middleware' => [CUAuth::class, AppTesters::class], function () {
137+
Route::get('profile', [UserController::class, 'show']);
138+
});
139+
```
140+
141+
```dotenv
142+
# File: .env
143+
APP_TESTERS=abc123,def456
144+
```
145+
146+
On non-production sites, the [AppTesters](Middleware/AppTesters.php) middleware checks the "APP_TESTERS" environment variable for a comma-separated list of users. If a user is logged in and not in the list, the middleware will return an HTTP_FORBIDDEN response.
147+
148+
The field used for looking up users is `netid` by default. It is configured in [config/cu-auth.php](../../config/cu-auth.php) file as `app_testers_field`.
149+
150+
151+
## Local Login
152+
For testing purposes, the environment variable "ALLOW_LOCAL_LOGIN" can be set to true to bypass the middleware for a currently authenticated user.
153+
```dotenv
154+
# File: .env
155+
ALLOW_LOCAL_LOGIN=true
156+

SHIBBOLETH.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Media 3 Server Configuration for Shibboleth
2+
3+
[CUAuth](README.md) can be configured to protect specific routes with Shibboleth authentication and manage multiple
4+
Identity Providers (IdPs).
5+
6+
Below is server configuration for using [CUAuth](README.md) with mod_shib on Media 3.
7+
8+
## Apache configuration
9+
10+
The vhost configuration determines which pages are protected by Shibboleth. The configuration below allows
11+
Laravel to use routing to determine when to authenticate the user.
12+
13+
```apache
14+
# File: /etc/apache2/conf.d/userdata/ssl/2_4/<username>/<sitename>/<sitename>.conf
15+
<Directory /home/<username>/public_html/<site>/public>
16+
...
17+
AuthType shibboleth
18+
ShibRequestSetting redirectToSSL 443
19+
# Laravel will determine when to authenticate, set to 1 if all pages should be protected
20+
ShibRequestSetting requireSession 0
21+
# Set the applicationId if not using the default IdP
22+
# ShibRequestSetting applicationId idselect-test
23+
require shibboleth
24+
</Directory>
25+
```
26+
27+
Use [CUAuth middleware](README.md#single-sign-on) to protect routes that need authorization. If all routes for the site
28+
should be protected by Shibboleth, `requireSession` can be set to `1`.
29+
30+
To utilize a Shibboleth `ApplicationOverride` configuration, the Apache vhost configuration for the site must specify
31+
the `applicationId`, which should be configured in shibboleth2.xml ([see below](#shibboleth-with-multiple-idps)).
32+
33+
34+
## PHP configuration
35+
36+
On Media 3 servers, Shibboleth attributes are available only on sites served with suphp. Sites using php-cgi
37+
only pass the validated user identifier. If you need to determine which IdP authenticated the user, you must use suphp.
38+
39+
> **Important**: Selection of suphp / php-cgi is set server-wide for each PHP version. Additionally, file and directory permissions must be properly set if using suphp. Media 3 support can help with this.
40+
41+
42+
## Shibboleth with Multiple IdPs
43+
44+
In `/etc/shibboleth/shibboleth2.xml`, specify identity providers in the `ApplicationDefaults` element. Use `ApplicationOverride` for alternate IdPs. Make sure to include the `MetadataProvider` for each IdP.
45+
46+
> Note: If all sites on a server should use the same IdP, modification of `shibboleth2.xml` is not necessary.
47+
48+
Key elements (can be set up for any Media 3 server):
49+
```xml
50+
<!-- File: /etc/shibboleth/shibboleth2.xml -->
51+
...
52+
<ApplicationDefaults ...>
53+
<Sessions ...>
54+
<!-- Default IdP-->
55+
<SSO entityID="https://shibidp.cit.cornell.edu/idp/shibboleth" ...>
56+
...
57+
</Sessions>
58+
<MetadataProvider url="https://shibidp.cit.cornell.edu/idp/shibboleth" backingFilePath="cornellidp.xml" ... />
59+
<MetadataProvider url="https://shibidp-test.cit.cornell.edu/idp/shibboleth" backingFilePath="cornell-test-idp.xml" ... />
60+
<MetadataProvider url="https://login.weill.cornell.edu/idp/saml2/idp/metadata.php" backingFilePath="weill-idp.xml" ... />
61+
<MetadataProvider url="https://login-test.weill.cornell.edu/idp/saml2/idp/metadata.php" backingFilePath="weill-test-idp.xml" ... />
62+
...
63+
<ApplicationOverride id="cit-test">
64+
<Sessions ...>
65+
<SSO discoveryURL="https://shibidp-test.cit.cornell.edu/idp/shibboleth" ...>
66+
...
67+
</Sessions>
68+
</ApplicationOverride>
69+
<ApplicationOverride id="idselect">
70+
<Sessions ...>
71+
<SSO discoveryURL="https://idselect.idm.cit.cornell.edu/idselect/select.html" ...>
72+
...
73+
</Sessions>
74+
</ApplicationOverride>
75+
<ApplicationOverride id="idselect-test">
76+
<Sessions ...>
77+
<SSO discoveryURL="https://idselect-test.idm.cit.cornell.edu/idselect/select.html" ...>
78+
...
79+
</Sessions>
80+
</ApplicationOverride>
81+
```

composer.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "cornell-custom-dev/laravel-cu-auth",
3+
"description": "A Laravel package for authentication and identity management at Cornell University",
4+
"license": "MIT",
5+
"type": "library",
6+
"require": {
7+
"php": "^8.2",
8+
"ext-openssl": "*",
9+
"illuminate/contracts": "^11.0|^12.0",
10+
"spatie/laravel-package-tools": "^1.92",
11+
"onelogin/php-saml": "^4.3"
12+
},
13+
"require-dev": {
14+
"laravel/pint": "^1.20",
15+
"orchestra/testbench": "^9.0|^10.0",
16+
"phpunit/phpunit": "^10.5|^11.5"
17+
},
18+
"autoload": {
19+
"psr-4": {
20+
"CornellCustomDev\\LaravelStarterKit\\CUAuth\\": "src"
21+
}
22+
},
23+
"autoload-dev": {
24+
"psr-4": {
25+
"CornellCustomDev\\LaravelStarterKit\\CUAuth\\Tests\\": "tests"
26+
}
27+
},
28+
"extra": {
29+
"laravel": {
30+
"providers": [
31+
"CornellCustomDev\\LaravelStarterKit\\CUAuth\\CUAuthServiceProvider"
32+
]
33+
}
34+
},
35+
"prefer-stable": true
36+
}

config/cu-auth.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
return [
4+
/*
5+
|--------------------------------------------------------------------------
6+
| Identity Manager
7+
|--------------------------------------------------------------------------
8+
|
9+
| The identity manager to use for user authentication. Options are:
10+
| - apache-shib: Apache mod_shib
11+
| - php-saml: OneLogin SAML PHP Toolkit
12+
|
13+
*/
14+
'identity_manager' => env('CU_AUTH_IDENTITY_MANAGER', 'apache-shib'),
15+
16+
/*
17+
|--------------------------------------------------------------------------
18+
| Require Local User
19+
|--------------------------------------------------------------------------
20+
|
21+
| Require a local user account in the application for the authenticated
22+
| remote user. This setting controls the CUAuthenticated event to handle
23+
| user login.
24+
|
25+
*/
26+
'require_local_user' => env('REQUIRE_LOCAL_USER', false),
27+
28+
/*
29+
|--------------------------------------------------------------------------
30+
| ApacheShib Configuration
31+
|--------------------------------------------------------------------------
32+
|
33+
| ApacheShib retrieves user data from server variables populated by the
34+
| Apache shibboleth module (mod_shib).
35+
|
36+
| The default user variable is "REMOTE_USER", but this may differ depending
37+
| on how mod_shib is configured.
38+
|
39+
| For local development without shibboleth, you can add
40+
| REMOTE_USER=<netid> to your project .env file to log in as that user.
41+
|
42+
*/
43+
'apache_shib_user_variable' => env('APACHE_SHIB_USER_VARIABLE', 'REMOTE_USER'),
44+
'remote_user_override' => env('REMOTE_USER'),
45+
46+
/*
47+
|--------------------------------------------------------------------------
48+
| PHP-SAML Configuration
49+
|--------------------------------------------------------------------------
50+
|
51+
| Note: Configuration for the OneLogin SAML PHP Toolkit can be found
52+
| in config/php-saml-toolkit.php.
53+
|
54+
| The default path of storage/app/keys is ignored by git in a standard
55+
| Laravel installation, so typically this does not need to be changed.
56+
|
57+
*/
58+
'cert-path' => storage_path(env('SAML_CERT_PATH', 'app/keys')),
59+
60+
/*
61+
|--------------------------------------------------------------------------
62+
| AppTesters Configuration
63+
|--------------------------------------------------------------------------
64+
|
65+
| Comma-separated list of users to allow in development environments.
66+
| APP_TESTERS_FIELD is the field on the user model to compare against.
67+
|
68+
*/
69+
'app_testers' => env('APP_TESTERS', ''),
70+
'app_testers_field' => env('APP_TESTERS_FIELD', 'netid'),
71+
72+
/*
73+
|--------------------------------------------------------------------------
74+
| Allow Local Login
75+
|--------------------------------------------------------------------------
76+
|
77+
| Allow Laravel password-based login? Typically, this would only be used
78+
| for local or automated testing.
79+
|
80+
*/
81+
'allow_local_login' => boolval(env('ALLOW_LOCAL_LOGIN', false)),
82+
];

0 commit comments

Comments
 (0)