Thank you for pointing me in the right direction! Unfortunately I’m not an expert either, and this sent me down a rabbit hole… but I have a working solution that does everything I want now.
I had to make some updates to my Authelia & Traefik forwardauth config as the authz endpoints you linked are somewhat newer in Authelia, and I was not using them yet. Once that was set and I updated my Traefik middleware to use the authz endpoint, was able to add a client in Authelia:
identity_provider:
oidc:
...
clients:
- client_id: 'sb-bearer-client'
client_secret: '$pbkdf2-redacted' #The corresponding Random Password is used when requesting token
public: false
scopes:
- 'authelia.bearer.authz'
audience:
- 'https://sb.example.net'
grant_types:
- 'client_credentials'
token_endpoint_auth_method: 'client_secret_basic'
And then add it to my access control rules:
access_control:
default_policy: deny
rules:
- domain:
- "sb.example.net"
resources:
- '/.client/manifest.json$'
- '/.client/[a-zA-Z0-9_-]+.png$'
- '/service_worker.js$'
policy: bypass
- domain:
- 'sb.example.net'
policy: 'one_factor'
subject: 'oauth2:client:sb-bearer-client'
# Establishes 2-factor auth for everything else
- domain:
- "*.example.net"
- "example.net"
policy: two_factor
subject:
- ["group:admins"]
- ["group:users"]
Can then request a bearer token with this call (sb-bearer-client-password should be the “random password” value generated by Authelia to correspond to the digest used in client_secret
:
curl --request POST \
--url 'https://auth.example.net/api/oidc/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic $(echo -n "sb-bearer-client:sb-bearer-client-password" | base64) \
--data grant_type=client_credentials \
--data scope='authelia.bearer.authz' \
--data audience='https://sb.example.net'
So the end result is:
- 2FA on Authelia GUI
- 1FA access with bearer token for API calls
- Bypass for the PWA elements
One challenge with this approach is that the tokens are, by default, short-lived per how I have Authelia configured. It’s possible to add a custom lifespan to the client in order to create longer-lived tokens, but without the ability to rotate them I’m hesitant use it that way.
Since I want to use this with iOS Shortcuts, I created a shortcut that requests a token, then passes it to a Silverbullet API call.
Here is the shortcut, in case useful to anyone else:
https://www.icloud.com/shortcuts/a102094da5054f7ea067ee0ddab4735b
Right now it just shows the “index” page from your space, but easy enough to change it to a POST call to add/edit notes.