Current section
Files
Jump to
Current section
Files
fdsn_plugs
README.md
README.md
# FdsnPlugs
[](https://gricad-gitlab.univ-grenoble-alpes.fr/OSUG/RESIF/fdsn_plugs/-/commits/main)
[](https://hex.pm/packages/fdsn_plugs)
[](https://hexdocs.pm/fdsn_plugs/)
Collection of plugs related to FDSN webservices.
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `fdsn_plugs` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:fdsn_plugs, "~> 0.9.0"}
]
end
```
## Usage
This module provides two supersets of plugs: `FdsnDataselectPlugs` and
`FdsnAvailabilityPlugs` to implement dataselect and availability web services.
### Phoenix
Add the plug collection to your pipeline:
```elixir
pipeline :fdsn do
plug :accepts, ["json", "text", "mseed"]
plug FdsnDataselectPlugs
end
```
### JWT authentication
`FdsnPlugs.JWTAuthentication` is included in both pipeline supersets. It
authenticates requests via JWT bearer tokens, supporting multiple token
authorities.
#### 1. Start one `FdsnPlugs.JwkStrategy` per authority in your supervision tree
Each strategy fetches and caches JWKS signing keys from the given URL.
```elixir
children = [
{FdsnPlugs.JwkStrategy,
name: :eida,
jwks_url: "https://geofon.gfz.de/eas2/jwk",
time_interval: 600_000,
first_fetch_sync: true},
{FdsnPlugs.JwkStrategy,
name: :other_authority,
jwks_url: "https://auth.example.com/jwks",
first_fetch_sync: true}
]
```
`first_fetch_sync` must be set to `true`.
##### Alternative: configuration via environment variable
`FdsnPlugs.JwkConfig.child_specs/0` reads a `JWT_AUTHORITIES` JSON array from
the environment and returns the corresponding child specs. Use it to keep the
supervision tree declarative:
```elixir
children =
FdsnPlugs.JwkConfig.child_specs() ++ [
# your other children…
]
```
The env var format is a JSON array of objects, each with a `"name"` and
`"jwks_url"`:
```bash
export JWT_AUTHORITIES='[
{"name":"eida","jwks_url":"https://geofon.gfz.de/eas2/jwk"},
{"name":"other","jwks_url":"https://auth.example.com/jwks","time_interval":3600000}
]'
```
If the env var is unset, empty, or malformed, `child_specs/0` returns `[]` and
no strategies are started.
#### 2. Configure which authorities the plug should try
Via application config:
```elixir
config :fdsn_plugs, :jwt_authorities, [:eida, :other_authority]
```
Via environment variable:
```elixir
config :fdsn_plugs, :jwt_authorities, FdsnPlugs.JwkConfig.authority_names()
```
Or inline in a custom pipeline:
```elixir
plug FdsnPlugs.JWTAuthentication, authorities: [:eida, :other_authority]
```
#### How it works
1. If `conn.assigns.user` is already set (e.g. HTTP Digest auth from your
application), the plug passes through.
2. If no `Authorization` header is present, the plug passes through.
3. On a `Bearer <token>` header, each authority is tried in order.
4. On success, all token claims are stored in `conn.assigns.jwt_claims` and the
`email` claim is stored in `conn.assigns.user`.
5. If no authority validates the token, a **401** response is returned with a
`WWW-Authenticate` header explaining the reason.
#### Testing with curl
The token must be the **raw JWT** (`access_token` value), not the full OAuth2
JSON response. Extract it with `jq`:
```bash
ACCESS_TOKEN=$(jq -r '.access_token' token.json)
curl --oauth2-bearer "$ACCESS_TOKEN" "https://your-server/fdsnws/dataselect/1/query?net=FR&sta=RUSF"
```
Or test directly against the EIDA JWKS without a server:
```bash
ACCESS_TOKEN=$(jq -r .access_token ~/Téléchargements/eidajwt.json) mix run bin/verify_jwt.exs
```
## Logging
The library uses Elixir's `Logger` for its log messages.
### Changing the log level during tests
Test log level is configured in `test/test_helper.exs` via `Logger.configure(level: :warning)`. The default is `:warning`; valid values are `:debug`, `:info`, `:warning`, and `:error`.
```elixir
# test/test_helper.exs
Logger.configure(level: :info)
```