Skip to content

Commit

Permalink
Merge pull request vtsykun#54 from vtsykun/feature/ldap-support
Browse files Browse the repository at this point in the history
LDAP authentication support
  • Loading branch information
vtsykun authored Jan 15, 2023
2 parents fdac87c + 1eb065d commit 945e80e
Show file tree
Hide file tree
Showing 58 changed files with 2,081 additions and 239 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Packeton - Private PHP package repository for vendors
Fork of [Packagist](https://github.com/composer/packagist).
The Open Source alternative of [Private Packagist for vendors](https://packagist.com), that based on [Satis](https://github.com/composer/satis) and [Packagist](https://github.com/composer/packagist).

### Legacy Symfony 3.4 version
**All** documentation here [docs.packeton.org](https://docs.packeton.org/)

[Legacy docs](../1.4/README.md)
### Legacy Symfony 3.4 version

Update to 2.0. [UPGRADE.md](./UPGRADE.md)

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"doctrine/doctrine-bundle": "^2.2",
"doctrine/orm": "^2.7",
"ezyang/htmlpurifier": "^4.16",
"firebase/php-jwt": "^6.3",
"knplabs/knp-menu-bundle": "^3.2",
"laminas/laminas-feed": "^2.20",
"nelmio/cors-bundle": "^2.2",
Expand Down
64 changes: 63 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ security:
packagist:
id: Packeton\Security\Provider\UserProvider

all_users:
chain:
providers: ['packagist']

firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
packages:
pattern: (^(.+\.json$|/p/|/zipball/|/feeds/.+(\.rss|\.atom)|/packages/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?(\.json|/changelog)|/packages/list\.json|/downloads/|/api/))+
api_basic: true
api_basic:
provider: all_users
stateless: true
context: main
user_checker: Packeton\Security\UserChecker
Expand All @@ -30,16 +35,11 @@ security:
lazy: true
pattern: .*
user_checker: Packeton\Security\UserChecker
form_login:
provider: packagist
login_path: /login
use_forward: false
check_path: /login
failure_path: null
'%default_login_provider%': '%default_login_options%'

remember_me:
secret: '%env(APP_SECRET)%'
user_providers: packagist
user_providers: all_users
name: pauth
always_remember_me: true
lifetime: 31104000 # 1y
Expand Down
15 changes: 10 additions & 5 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,23 @@ parameters:
'Packeton\Entity\User': ['getApiToken', 'unserialize', 'getGithubToken', 'getPassword', 'getSalt', 'getPlainPassword', '!regex /^(add|set)/']
'Packeton\Entity\Package': ['getCredentials', '!regex /^(add|set)/']

default_login_provider: 'form_login'
default_login_options:
provider: all_users
login_path: /login
use_forward: false
check_path: /login
failure_path: null

services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
$redis: '@snc_redis.default'
$jwtTokenConfig: '%packeton_jws_config%'
$jwtSignAlgorithm: '%packeton_jws_algo%'
'Symfony\Component\Security\Core\User\UserCheckerInterface': '@Packeton\Security\UserChecker'

Packeton\:
Expand Down Expand Up @@ -77,11 +87,6 @@ services:
arguments:
$config: '%packeton_archive_opts%'

Packeton\Security\Api\ApiTokenAuthenticator:
abstract: true
arguments:
$userProvider: '@Packeton\Security\Provider\UserProvider'

Packeton\DBAL\OpensslCrypter:
public: true
arguments:
Expand Down
23 changes: 22 additions & 1 deletion docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,25 @@

# Introduction
- [Overview](readme.md)
- [Installation](installation.md)

# Setup
- [Installation](installation.md)
- [Using docker](installation-docker.md)

# Usage
- [Administration](usage/README.md)
- [Admin API](usage/api.md)
- [Outgoing Webhook](webhook.md)
- [Intro](webhook.md)
- [Examples](webhook.md)
- [Secrets](webhook/webhook-secrets.md)
- [Security Policy](webhook/wh-security.md)
- [Testing](webhook/wh-test.md)
- [Update Webhooks](usage/update-packages.md)

- [User Authentication](authentication.md)
- [JWT Configuration](authentication-jwt.md)
- [LDAP Configuration](authentication-ldap.md)

# Development
- [Contributing](dev/contributing.md)
102 changes: 102 additions & 0 deletions docs/authentication-jwt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# JWT API Authentication

By default, packeton is storage api tokens in database for each user. But when user
loaded from custom user provider, like LDAP need to enable JWT configuration to use API. So Packeton can be
configured with a non-standard login type to support [JSON Web Tokens](https://en.wikipedia.org/wiki/JSON_Web_Token).

The JSON Web Token integration in Packeton uses the [Firebase library](https://github.com/firebase/php-jwt).
Also, JWT authentication can be enabled only for API.

Add `yaml` configuration file to path `config/packages/`, for example `config/packages/jwt.yaml` to enable it.

```yaml
packeton:
jwt_authentication:
private_key: '%kernel.project_dir%/var/jwt/eddsa-key.pem'
public_key: '%kernel.project_dir%/var/jwt/eddsa-public.pem'
```
Full configurations:
```yaml
# config/packages/config/packages/jwt.yaml
packeton:
jwt_authentication:
private_key: '%kernel.project_dir%/var/jwt/eddsa-key.pem' # required for token sign
public_key: '%kernel.project_dir%/var/jwt/eddsa-public.pem' # required for token verification
passphrase: ~
algo: EdDSA # Sign algo, here libsodium EdDSA
```
## Generate the public/private keys
```
bin/console packagist:jwt:generate-keypair

bin/console packagist:jwt:generate-keypair --overwrite
```

Available options:
* --overwrite will overwrite your keys if they already exist.

If keys already exists, a warning message will be raised to prevent you from overwriting your keys accidentally.

### JWT Token TTL.

JWT Token is never expire. It was done for compatibility with composer basic HTTP authorization.
Each time the api is called, Packeton is checked that the user exists in the database and that
he has the same set of permissions and roles.

### Digital signatures algos.

We support all algos from Firebase lib: HMAC, OpenSSL RSA, OpenSSL

Rsa, HMAC, EdDSA algorithms generate invariant tokens, i.e. the value of the token will be constant for the same user.
It might be convenient as the app does not store the generated tokens.

Example how to change algo:

```yaml
packeton:
jwt_authentication:
...
algo: RS256 # RSA 256
```
### Generating keys using OpenSSL
Example, how to generate an RSA private key, `key.pem` - private key. `public.pem` - public

```
openssl genrsa -out key.pem 2048
openssl rsa -in key.pem -outform PEM -pubout -out public.pem
```
Example, how to generate an ES256 (elliptic curve) key pairs.
```
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
openssl ec -in key.pem -pubout -out public.pem
```
## Obtain the token
You can run command `packagist:user:manager` to show the api token:
```
bin/console packagist:user:manager admin --show-token --token-format=jwt
```
Or you can found api token on your profile page.
[![Keys](img/jwt_keys.png)](img/jwt_keys.png)
### Use the token
Simply use the JWT, like standard API token for composer api.
#### Cache LDAP user loading.
Since 2.0 composer downloads all packages in parallel, it may run more 12 request at the same time.
To prevent calls external LDAP provider each time for JWT token verify, the obtained LDAP user object
placed to cache with 60 sec TTL.
Loading

0 comments on commit 945e80e

Please sign in to comment.