Skip to content

Commit

Permalink
Merge pull request #196 from silinternational/feature/silauth-module
Browse files Browse the repository at this point in the history
directly include the silauth module
  • Loading branch information
briskt authored May 18, 2024
2 parents e6ab52a + 2143ada commit cc8413d
Show file tree
Hide file tree
Showing 63 changed files with 4,818 additions and 181 deletions.
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,83 @@ can be autoloaded, to use as the logger within ExpiryDate.

The `profileUrl` parameter is for the URL of where to send the user if they
want/need to update their profile.

### SilAuth SimpleSAMLphp module

SimpleSAMLphp auth module implementing custom business logic:

- authentication
- rate limiting
- status endpoint

[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://raw.githubusercontent.com/silinternational/simplesamlphp-module-silauth/develop/LICENSE)

#### Database Migrations
To create another database migration file, run the following (replacing
`YourMigrationName` with whatever you want the migration to be named, using
CamelCase):

make migration NAME=YourMigrationName

#### Rate Limiting
SilAuth will rate limit failed logins by username and by every untrusted IP
address from a login attempt.

##### tl;dr ("the short version")
If there have been more than 10 failed logins for a given username (or IP
address) within the past hour, a captcha will be included in the webpage. The
user may or may not have to directly interact with the captcha, though.

If there have been more than 50 failed logins for that username (or IP address)
within the past hour, logins for that username (or IP address) will be blocked
for up to an hour.

##### Details
For each login attempt, if it has too many failed logins within the last hour
(aka. recent failed logins) for the given username OR for any single untrusted
IP address associated with the current request, it will do one of the following:

- If there are fewer than `Authenticator::REQUIRE_CAPTCHA_AFTER_NTH_FAILED_LOGIN`
recent failures: process the request normally.
- If there are at least that many, but fewer than
`Authenticator::BLOCK_AFTER_NTH_FAILED_LOGIN`: require the user to pass a
captcha.
- If there are more than that: block that login attempt for `(recent failures
above the limit)^2` seconds after the most recent failed login, with a
minimum of 3 (so blocking for 9 seconds).
- Note: the blocking time is capped at an hour, so if no more failures occur,
then the user will be unblocked in no more than an hour.

See `features/login.feature` for descriptions of how various situations are
handled. That file not only contains human-readable scenarios, but those are
also actual tests that are run to ensure those descriptions are correct.

##### Example 1

- If `BLOCK_AFTER_NTH_FAILED_LOGIN` is 50, and
- if `REQUIRE_CAPTCHA_AFTER_NTH_FAILED_LOGIN` is 10, and
- if there have been 4 failed login attempts for `john_smith`, and
- there have been 10 failed login attempts from `11.22.33.44`, and
- there have been 3 failed login attempts from `192.168.1.2`, and
- someone tries to login as `john_smith` from `192.168.1.2` and their request
goes through a proxy at `11.22.33.44`, then
- they will have to pass a captcha, but they will not yet be blocked.

##### Example 2

- However, if all of the above is true, but
- there have now been 55 failed login attempts from `11.22.33.44`, then
- any request involving that IP address will be blocked for 25 seconds after
the most recent of those failed logins.

#### Excluding trusted IP addresses from IP address based rate limiting
Since this application enforces rate limits based on the number of recent
failed login attempts by both username and IP address, and since it looks at
both the REMOTE_ADDR and the X-Forwarded-For header for IP addresses, you will
want to list any IP addresses that should NOT be rate limited (such as your
load balancer) in the TRUSTED_IP_ADDRESSES environment variable (see
`local.env.dist`).

#### Status Check
To check the status of the website, you can access this URL:
`https://(your domain name)/module.php/silauth/status.php`
68 changes: 67 additions & 1 deletion actions-services.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
version: '3'
services:

# the db container is used by the silauth module
db:
image: mariadb:10
environment:
MYSQL_ROOT_PASSWORD: r00tp@ss!
MYSQL_DATABASE: silauth
MYSQL_USER: silauth
MYSQL_PASSWORD: silauth

app:
build: .
depends_on:
Expand All @@ -10,6 +20,10 @@ services:
- pwmanager.local
- test-browser
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=silauth
- MYSQL_USER=silauth
- MYSQL_PASSWORD=silauth
- PROFILE_URL_FOR_TESTS=http://pwmanager.local/module.php/core/authenticate.php?as=ssp-hub
- [email protected]
- ADMIN_PASS=b
Expand Down Expand Up @@ -60,6 +74,8 @@ services:

ssp-idp1.local:
build: .
depends_on:
- db
volumes:
# Utilize custom certs
- ./development/idp-local/cert:/data/vendor/simplesamlphp/simplesamlphp/cert
Expand All @@ -83,7 +99,10 @@ services:

# Include the features folder (for the FakeIdBrokerClient class)
- ./features:/data/features
command: 'bash -c "/data/enable-exampleauth-module.sh && /data/run.sh"'
command: >
bash -c "whenavail db 3306 60 /data/vendor/simplesamlphp/simplesamlphp/modules/silauth/lib/Auth/Source/yii migrate --interactive=0 &&
/data/enable-exampleauth-module.sh &&
/data/run.sh"
environment:
ADMIN_EMAIL: "[email protected]"
ADMIN_PASS: "a"
Expand All @@ -101,6 +120,11 @@ services:
SECURE_COOKIE: "false"
SHOW_SAML_ERRORS: "true"
THEME_USE: "default"
MYSQL_HOST: "db"
MYSQL_DATABASE: "silauth"
MYSQL_USER: "silauth"
MYSQL_PASSWORD: "silauth"
BASE_URL_PATH: "http://ssp-idp1.local/"

ssp-idp2.local:
build: .
Expand Down Expand Up @@ -176,3 +200,45 @@ services:
- SAML20_IDP_ENABLE=false
- ADMIN_PROTECT_INDEX_PAGE=false
- THEME_USE=default

# the broker and brokerDb containers are used by the silauth module
broker:
image: silintl/idp-id-broker:latest
ports:
- "80"
depends_on:
- brokerDb
environment:
IDP_NAME: "idp"
MYSQL_HOST: "brokerDb"
MYSQL_DATABASE: "broker"
MYSQL_USER: "user"
MYSQL_PASSWORD: "pass"
EMAIL_SERVICE_accessToken: "dummy"
EMAIL_SERVICE_assertValidIp: "false"
EMAIL_SERVICE_baseUrl: "dummy"
EMAILER_CLASS: Sil\SilIdBroker\Behat\Context\fakes\FakeEmailer
HELP_CENTER_URL: "https://example.org/help"
PASSWORD_FORGOT_URL: "https://example.org/forgot"
PASSWORD_PROFILE_URL: "https://example.org/profile"
SUPPORT_EMAIL: "[email protected]"
EMAIL_SIGNATURE: "one red pill, please"
API_ACCESS_KEYS: "test-cli-abc123"
APP_ENV: "prod"
MFA_TOTP_apiBaseUrl: not_needed_here
MFA_TOTP_apiKey: not_needed_here
MFA_TOTP_apiSecret: not_needed_here
MFA_WEBAUTHN_apiBaseUrl: not_needed_here
MFA_WEBAUTHN_apiKey: not_needed_here
MFA_WEBAUTHN_apiSecret: not_needed_here
command: "bash -c 'whenavail brokerDb 3306 60 ./yii migrate --interactive=0 && ./run.sh'"

brokerDb:
image: mariadb:10
ports:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: "r00tp@ss!"
MYSQL_DATABASE: "broker"
MYSQL_USER: "user"
MYSQL_PASSWORD: "pass"
6 changes: 6 additions & 0 deletions behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ default:
expiry_features:
paths: [ '%paths.base%//features//expirychecker.feature' ]
contexts: [ 'ExpiryContext' ]
login_features:
paths: [ '%paths.base%//features//login.feature' ]
contexts: [ 'LoginContext' ]
material_features:
paths: [ '%paths.base%//features//material.feature' ]
contexts: [ 'FeatureContext' ]
Expand All @@ -15,3 +18,6 @@ default:
profilereview_features:
paths: [ '%paths.base%//features//profilereview.feature' ]
contexts: [ 'ProfileReviewContext' ]
status_features:
paths: [ '%paths.base%//features//status.feature' ]
contexts: [ 'StatusContext' ]
12 changes: 10 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,25 @@
"ext-gmp": "*",
"ext-json": "*",
"ext-memcached": "*",
"codemix/yii2-streamlog": "^1.3",
"simplesamlphp/simplesamlphp": "^1.19.6",
"simplesamlphp/composer-module-installer": "1.1.8",
"silinternational/simplesamlphp-module-silauth": "^7.1.1",
"rlanvin/php-ip": "^1.0",
"silinternational/ssp-utilities": "^1.1.0",
"silinternational/simplesamlphp-module-material": "^8.1.1",
"silinternational/simplesamlphp-module-sildisco": "^4.0.0",
"silinternational/php-env": "^3.1.0",
"silinternational/psr3-adapters": "^3.1",
"silinternational/yii2-json-log-targets": "^2.0",
"gettext/gettext": "^4.8@dev",
"silinternational/idp-id-broker-php-client": "^4.3",
"sinergi/browser-detector": "^6.1"
"sinergi/browser-detector": "^6.1",
"yiisoft/yii2": "~2.0.12",
"yiisoft/yii2-gii": "^2.0",
"fillup/fake-bower-assets": "^2.0",
"google/recaptcha": "^1.1",
"psr/log": "^1.0",
"monolog/monolog": "^1.22"
},
"require-dev": {
"behat/behat": "^3.8",
Expand Down
Loading

0 comments on commit cc8413d

Please sign in to comment.