Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 27 additions & 18 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,33 @@ Most configuration can be set directly using environment variables or flags. The

### HTTP configuration variables

| Environment variable | Default | Required | Description |
| ------------------------------------------ | ------- | -------- | ----------------------------------------------------- |
| `SHIORI_HTTP_ENABLED` | True | No | Enable HTTP service |
| `SHIORI_HTTP_PORT` | 8080 | No | Port number for the HTTP service |
| `SHIORI_HTTP_ADDRESS` | : | No | Address for the HTTP service |
| `SHIORI_HTTP_ROOT_PATH` | / | No | Root path for the HTTP service |
| `SHIORI_HTTP_ACCESS_LOG` | True | No | Logging accessibility for HTTP requests |
| `SHIORI_HTTP_SERVE_WEB_UI` | True | No | Serving Web UI via HTTP. Disable serves only the API. |
| `SHIORI_HTTP_SECRET_KEY` | | **Yes** | Secret key for HTTP sessions. |
| `SHIORI_HTTP_BODY_LIMIT` | 1024 | No | Limit for request body size |
| `SHIORI_HTTP_READ_TIMEOUT` | 10s | No | Maximum duration for reading the entire request |
| `SHIORI_HTTP_WRITE_TIMEOUT` | 10s | No | Maximum duration before timing out writes |
| `SHIORI_HTTP_IDLE_TIMEOUT` | 10s | No | Maximum amount of time to wait for the next request |
| `SHIORI_HTTP_DISABLE_KEEP_ALIVE` | true | No | Disable HTTP keep-alive connections |
| `SHIORI_HTTP_DISABLE_PARSE_MULTIPART_FORM` | true | No | Disable pre-parsing of multipart form |
| `SHIORI_SSO_PROXY_AUTH_ENABLED` | false | No | Enable SSO Auth Proxy Header |
| `SHIORI_SSO_PROXY_AUTH_HEADER_NAME` | Remote-User | No | List of CIDRs of trusted proxies |
| `SHIORI_SSO_PROXY_AUTH_TRUSTED` | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7 | No | List of CIDRs of trusted proxies |
| Environment variable | Default | Required | Description |
|--------------------------------------------|-----------------------------------------------------|----------|-------------------------------------------------------|
| `SHIORI_HTTP_ENABLED` | True | No | Enable HTTP service |
| `SHIORI_HTTP_PORT` | 8080 | No | Port number for the HTTP service |
| `SHIORI_HTTP_ADDRESS` | : | No | Address for the HTTP service |
| `SHIORI_HTTP_ROOT_PATH` | / | No | Root path for the HTTP service |
| `SHIORI_HTTP_ACCESS_LOG` | True | No | Logging accessibility for HTTP requests |
| `SHIORI_HTTP_SERVE_WEB_UI` | True | No | Serving Web UI via HTTP. Disable serves only the API. |
| `SHIORI_HTTP_SECRET_KEY` | | **Yes** | Secret key for HTTP sessions. |
| `SHIORI_HTTP_BODY_LIMIT` | 1024 | No | Limit for request body size |
| `SHIORI_HTTP_READ_TIMEOUT` | 10s | No | Maximum duration for reading the entire request |
| `SHIORI_HTTP_WRITE_TIMEOUT` | 10s | No | Maximum duration before timing out writes |
| `SHIORI_HTTP_IDLE_TIMEOUT` | 10s | No | Maximum amount of time to wait for the next request |
| `SHIORI_HTTP_DISABLE_KEEP_ALIVE` | true | No | Disable HTTP keep-alive connections |
| `SHIORI_HTTP_DISABLE_PARSE_MULTIPART_FORM` | true | No | Disable pre-parsing of multipart form |
| `SHIORI_SSO_PROXY_AUTH_ENABLED` | false | No | Enable SSO Auth Proxy Header |
| `SHIORI_SSO_PROXY_AUTH_HEADER_NAME` | Remote-User | No | List of CIDRs of trusted proxies |
| `SHIORI_SSO_PROXY_AUTH_TRUSTED` | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7 | No | List of CIDRs of trusted proxies |
| `SHIORI_OIDC_ENABLED` | false | No | Enable OIDC Authentication |
| `SHIORI_OIDC_ISSUER` | | No | OIDC Issuer URL |
| `SHIORI_OIDC_CLIENT_ID` | | No | OIDC Client ID |
| `SHIORI_OIDC_CLIENT_SECRET` | | No | OIDC Client Secret |
| `SHIORI_OIDC_REDIRECT_URL` | | No | OIDC Redirect URL |
| `SHIORI_OIDC_SCOPES` | openid,profile,email | No | OIDC Scopes (comma separated) |
| `SHIORI_OIDC_USERNAME_CLAIM` | preferred_username | No | OIDC Username Claim |
| `SHIORI_OIDC_AUTO_REGISTER` | false | No | Automatically register new OIDC users |
| `SHIORI_OIDC_PROVIDER_NAME` | OIDC | No | Name of the OIDC Provider |

### Storage Configuration

Expand Down
49 changes: 49 additions & 0 deletions docs/swagger/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,26 @@ const docTemplate = `{
}
}
},
"/api/v1/auth/config": {
"get": {
"description": "Get authentication configuration like OIDC status",
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Get authentication configuration",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api_v1.AuthConfigResponse"
}
}
}
}
},
"/api/v1/auth/login": {
"post": {
"consumes": [
Expand Down Expand Up @@ -265,6 +285,24 @@ const docTemplate = `{
}
}
},
"/api/v1/auth/oidc/callback": {
"get": {
"tags": [
"Auth"
],
"summary": "OIDC callback URL",
"responses": {}
}
},
"/api/v1/auth/oidc/login": {
"get": {
"tags": [
"Auth"
],
"summary": "Redirect to OIDC provider for login",
"responses": {}
}
},
"/api/v1/auth/refresh": {
"post": {
"produces": [
Expand Down Expand Up @@ -731,6 +769,17 @@ const docTemplate = `{
}
},
"definitions": {
"api_v1.AuthConfigResponse": {
"type": "object",
"properties": {
"oidc_enabled": {
"type": "boolean"
},
"oidc_provider_name": {
"type": "string"
}
}
},
"api_v1.bookmarkTagPayload": {
"type": "object",
"required": [
Expand Down
49 changes: 49 additions & 0 deletions docs/swagger/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,26 @@
}
}
},
"/api/v1/auth/config": {
"get": {
"description": "Get authentication configuration like OIDC status",
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Get authentication configuration",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api_v1.AuthConfigResponse"
}
}
}
}
},
"/api/v1/auth/login": {
"post": {
"consumes": [
Expand Down Expand Up @@ -254,6 +274,24 @@
}
}
},
"/api/v1/auth/oidc/callback": {
"get": {
"tags": [
"Auth"
],
"summary": "OIDC callback URL",
"responses": {}
}
},
"/api/v1/auth/oidc/login": {
"get": {
"tags": [
"Auth"
],
"summary": "Redirect to OIDC provider for login",
"responses": {}
}
},
"/api/v1/auth/refresh": {
"post": {
"produces": [
Expand Down Expand Up @@ -720,6 +758,17 @@
}
},
"definitions": {
"api_v1.AuthConfigResponse": {
"type": "object",
"properties": {
"oidc_enabled": {
"type": "boolean"
},
"oidc_provider_name": {
"type": "string"
}
}
},
"api_v1.bookmarkTagPayload": {
"type": "object",
"required": [
Expand Down
32 changes: 32 additions & 0 deletions docs/swagger/swagger.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
definitions:
api_v1.AuthConfigResponse:
properties:
oidc_enabled:
type: boolean
oidc_provider_name:
type: string
type: object
api_v1.bookmarkTagPayload:
properties:
tag_id:
Expand Down Expand Up @@ -305,6 +312,19 @@ paths:
summary: Update account information
tags:
- Auth
/api/v1/auth/config:
get:
description: Get authentication configuration like OIDC status
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/api_v1.AuthConfigResponse'
summary: Get authentication configuration
tags:
- Auth
/api/v1/auth/login:
post:
consumes:
Expand Down Expand Up @@ -353,6 +373,18 @@ paths:
summary: Get information for the current logged in user
tags:
- Auth
/api/v1/auth/oidc/callback:
get:
responses: {}
summary: OIDC callback URL
tags:
- Auth
/api/v1/auth/oidc/login:
get:
responses: {}
summary: Redirect to OIDC provider for login
tags:
- Auth
/api/v1/auth/refresh:
post:
produces:
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
git.sr.ht/~emersion/go-sqlite3-fts5 v0.0.0-20250706113457-213d0e8755e5
github.com/PuerkitoBio/goquery v1.10.3
github.com/blang/semver v3.5.1+incompatible
github.com/coreos/go-oidc/v3 v3.17.0
github.com/disintegration/imaging v1.6.2
github.com/fatih/color v1.18.0
github.com/go-shiori/go-epub v1.2.2-0.20241010194245-bd691046db94
Expand Down Expand Up @@ -37,6 +38,7 @@ require (
golang.org/x/crypto v0.42.0
golang.org/x/image v0.31.0
golang.org/x/net v0.44.0
golang.org/x/oauth2 v0.35.0
golang.org/x/term v0.35.0
modernc.org/sqlite v1.39.0
)
Expand Down Expand Up @@ -66,6 +68,7 @@ require (
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
Expand Down Expand Up @@ -64,6 +66,8 @@ github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIp
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
Expand Down Expand Up @@ -339,6 +343,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down
34 changes: 34 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ type HttpConfig struct {
SSOProxyAuth bool `env:"SSO_PROXY_AUTH_ENABLED,default=false"`
SSOProxyAuthHeaderName string `env:"SSO_PROXY_AUTH_HEADER_NAME,default=Remote-User"`
SSOProxyAuthTrusted []string `env:"SSO_PROXY_AUTH_TRUSTED,default=10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7"`

OIDCEnabled bool `env:"OIDC_ENABLED,default=false"`
OIDCIssuer string `env:"OIDC_ISSUER"`
OIDCClientID string `env:"OIDC_CLIENT_ID"`
OIDCClientSecret string `env:"OIDC_CLIENT_SECRET"`
OIDCRedirectURL string `env:"OIDC_REDIRECT_URL"`
OIDCScopes string `env:"OIDC_SCOPES,default=openid,profile,email"`
OIDCUsernameClaim string `env:"OIDC_USERNAME_CLAIM,default=preferred_username"`
OIDCAutoRegister bool `env:"OIDC_AUTO_REGISTER,default=false"`
OIDCProviderName string `env:"OIDC_PROVIDER_NAME,default=OIDC"`
}

// SetDefaults sets the default values for the configuration
Expand Down Expand Up @@ -159,13 +169,37 @@ func (c *Config) DebugConfiguration(logger *logrus.Logger) {
logger.Debugf(" SHIORI_SSO_PROXY_AUTH_ENABLED: %t", c.Http.SSOProxyAuth)
logger.Debugf(" SHIORI_SSO_PROXY_AUTH_HEADER_NAME: %s", c.Http.SSOProxyAuthHeaderName)
logger.Debugf(" SHIORI_SSO_PROXY_AUTH_TRUSTED: %v", c.Http.SSOProxyAuthTrusted)
logger.Debugf(" SHIORI_OIDC_ENABLED: %t", c.Http.OIDCEnabled)
logger.Debugf(" SHIORI_OIDC_ISSUER: %s", c.Http.OIDCIssuer)
logger.Debugf(" SHIORI_OIDC_CLIENT_ID: %s", c.Http.OIDCClientID)
logger.Debugf(" SHIORI_OIDC_CLIENT_SECRET: %d characters", len(c.Http.OIDCClientSecret))
logger.Debugf(" SHIORI_OIDC_REDIRECT_URL: %s", c.Http.OIDCRedirectURL)
logger.Debugf(" SHIORI_OIDC_SCOPES: %s", c.Http.OIDCScopes)
logger.Debugf(" SHIORI_OIDC_USERNAME_CLAIM: %s", c.Http.OIDCUsernameClaim)
logger.Debugf(" SHIORI_OIDC_AUTO_REGISTER: %t", c.Http.OIDCAutoRegister)
logger.Debugf(" SHIORI_OIDC_PROVIDER_NAME: %s", c.Http.OIDCProviderName)
}

func (c *Config) IsValid() error {
if err := c.Http.IsValid(); err != nil {
return fmt.Errorf("http configuration is invalid: %w", err)
}

if c.Http.OIDCEnabled {
if c.Http.OIDCIssuer == "" {
return fmt.Errorf("OIDC issuer is required when OIDC is enabled")
}
if c.Http.OIDCClientID == "" {
return fmt.Errorf("OIDC client ID is required when OIDC is enabled")
}
if c.Http.OIDCClientSecret == "" {
return fmt.Errorf("OIDC client secret is required when OIDC is enabled")
}
if c.Http.OIDCRedirectURL == "" {
return fmt.Errorf("OIDC redirect URL is required when OIDC is enabled")
}
}

return nil
}

Expand Down
21 changes: 21 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -116,4 +117,24 @@ func TestConfigIsValid(t *testing.T) {
cfg.Http.RootPath = "/invalid"
require.Error(t, cfg.IsValid())
})

t.Run("verify oidc params", func(t *testing.T) {
cfg := ParseServerConfiguration(context.TODO(), log)
cfg.Http.OIDCEnabled = true
assert.Error(t, cfg.IsValid())
cfg.Http.OIDCIssuer = "http://issuer"
assert.Error(t, cfg.IsValid())
cfg.Http.OIDCClientID = "client-id"
assert.Error(t, cfg.IsValid())
cfg.Http.OIDCClientSecret = "client-secret"
assert.Error(t, cfg.IsValid())
cfg.Http.OIDCRedirectURL = "http://redirect.url"
require.NoError(t, cfg.IsValid())
})
}

func TestDebugConfiguration(t *testing.T) {
log := logrus.New()
cfg := ParseServerConfiguration(context.TODO(), log)
cfg.DebugConfiguration(log)
}
Loading
Loading