Git Product home page Git Product logo

greenpau / caddy-security Goto Github PK

View Code? Open in Web Editor NEW
1.2K 17.0 68.0 365 KB

๐Ÿ” Authentication, Authorization, and Accounting (AAA) App and Plugin for Caddy v2. ๐Ÿ’Ž Implements Form-Based, Basic, Local, LDAP, OpenID Connect, OAuth 2.0 (Github, Google, Facebook, Okta, etc.), SAML Authentication. MFA/2FA with App Authenticators and Yubico. ๐Ÿ’Ž Authorization with JWT/PASETO tokens. ๐Ÿ”

Home Page: https://authcrunch.com/

License: Apache License 2.0

Makefile 3.11% Go 95.73% Shell 0.99% HTML 0.17%
caddy-plugin caddy2 security jwt authorization authentication auth paseto paseto-tokens saml

caddy-security's Introduction

caddy-security

Security App and Plugin for Caddy v2. It includes:

  • Authentication Plugin for implementing Form-Based, Basic, Local, LDAP, OpenID Connect, OAuth 2.0, SAML Authentication
  • Authorization Plugin for HTTP request authorization based on JWT/PASETO tokens
  • Credentials Plugin for managing credentials for various integrations

Please show your appreciation for this work and โญ โญ โญ

Please consider sponsoring this project via Github Sponsors!

Please ask questions either here or via LinkedIn. I am happy to help you! @greenpau

Documentation: docs.authcrunch.com

Docker Container: authcrunch/authcrunch

Configuration Examples: here

Security Policy: SECURITY.md

caddy-security's People

Contributors

dbranco-sdc avatar devinmccode avatar freddyheppell avatar github-actions[bot] avatar greenpau avatar lennartschoch avatar moschlar avatar sergiuczm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

caddy-security's Issues

feature: connected accounts with LDAP, OAuth, SAML

A clear and concise description of what you want the system to do.

Scenarios

  1. A locally-authenticated user browses to "Connected Accounts" tab in "Portal Settings".
    There, the user may click a button to associate OAuth account (Google, Facebook, etc.) with the local user account.
  2. A user signs in with OAuth and lands on "portal" page. There, the user has an option to create an account in local user database.

In local database, add a list of maps.

  • For LDAP, add realm and dn fields
  • For OAuth, add provider and id fields

Question with OAuth:

  1. what is the id associated with a provider
  2. local the user in local database. requires editing go-identity

feature: multi-domain cookie configuration

A clear and concise description of what you want the system to do.

Let's say authentication portal serves 2 domains: foo.bar and bar.baz.

Currently, this requires to have separate portal instances.

This feature would allowing auto-discovering which cookie to issue/revoke based on the host the user is accessing.

What are the Caddyfile directives that need to be added.

Add Caddyfile directive:

{
  security {
    # currently, the domain is set like this.
    # cookie domain foo.bar
    # cookie lifetime 900

    # with this feature
    cookie foo.bar lifetime 900
    cookie bar.baz lifetime 900
  }
}

This also paves the way to allow issuing cross-domain cookies, i.e. a user authenticates in domain foo.bar and then, using Javascript, automatically gets cookies for domain bar.foo, 'bar.baz`, etc.

feature: API for changing user password

A clear and concise description of what you want to accomplish.

Is there a way to change password via API endpoint?

I have found only this to get user information:
https://authp.github.io/docs/authenticate/misc#user-identity

Can I do something like this:
curl -X PATCH https://auth.myfiosgateway.com:8443/whoami -d '{"password": "new-password"}'

Eventually I would like to have my own customized page similar to
https://github.com/greenpau/caddy-security/blob/a8591001dafe6aa0147242b2bc13b8e3ceaac65f/README.md#user-settings
to change user password via my webUI.

Is there a swagger documentation of API?

Thanks!

Github backend requests both read and write access

When using the github backend, the scope requested is user, which includes both read and write permissions to user data: https://github.com/greenpau/caddy-auth-portal/blob/0f64ae51b30682557cfa1ffb9dedcc92dc689aaf/caddyfile.go#L270
This is not ideal, since caddy shouldn't be changing user data. Instead, we could use the scope read:user which requests only read access.

Github documentation: https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps

This issue was first opened here: https://github.com/greenpau/caddy-auth-portal/issues/230

question: Migrating from caddy-auth-portal, and functionality.

It seems there's been a refactor to bring portal and authorize into this project. Your readme says "Please open an issue if you need help migrating configurations from caddy-auth-portal and caddy-authorize (aka caddy-auth-jwt)."

That sounds like exactly what I want to do! I am assuming that I need to use this repository (to build into my container), rather than the old auth-portal, and authorize? Do I need to add anything else (aaasf)?

Is this currently the same syntax and functionality, but a building block towards expanded functionality...or is there something in here that expands on the previous functionality?

question: Keeping users logged in longer?

I'm a bit confused on how to keep users logged in for longer. I set my cookie lifetime to 1440, and it definitely wasn't lasting that long. I would just get booted from my services and have to login again every once in a while.

question: Environment variables in Google OAuth example

I want to set up Google OAuth in front of various services in my existing Caddy set up. Looking through the example file:
https://github.com/authp/authp.github.io/blob/main/assets/conf/oauth/google/Caddyfile

What is JWT_SHARED_KEY?

Is the (tls_config) necessary? That appears to be using manual certs instead of Let's Encrypt?

https://assetq.myfiosgateway.com - I assume this should be like https://myservice.mydomain.com.

Presumably this could run on port 80 and 443 instead of the non-standard ports?

LDAP doesn't work

Describe the issue

LDAP doesn't work. I got this problem when starting or reload a config with LDAP included:

reload: sending configuration to instance: caddy responded with error: HTTP 400: {"error":"loading config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 18: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 2: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'authentication': provision http.handlers.authentication: loading authentication providers: module name 'authorizer': provision http.authentication.providers.authorizer: loading security app module: provision security: backend configuration for \"myportal\" portal failed: no username found"}

Configuration

{
	servers :443 {
		protocol {
			experimental_http3
		}
	}
	servers :8448 {
		protocol {
			experimental_http3
		}
	}
	#debug
	admin :2019 {
		origins 192.168.170.2
	}

	security {
		authentication portal myportal {
			crypto default token lifetime 120
			crypto key sign-verify <my-key>
			cookie domain mydomain.com
			backends {
				ldap_backend {
					method ldap
					realm ldap
					servers {
						ldap://ldap.mydomain.com
					}
					attributes {
						name givenName
						surname sn
						username sAMAccountName
						member_of memberOf
						email mail
					}
					username "CN=readonly,CN=Sysusers,DC=mydomain,DC=com"
					password "password"
					search_base_dn "OU=Users,OU=Accounts,DC=mydomain,DC=com"
					search_filter "(&(|(sAMAccountName=%s)(mail=%s))(objectclass=user))"
					groups {
						"CN=app1,OU=Services,DC=mydomain,DC=com" app1
						"CN=app2,OU=Services,DC=mydomain,DC=com" app2
						"CN=app3,OU=Services,DC=mydomain,DC=com" app3
						"CN=app4,OU=Services,DC=mydomain,DC=com" app4
					}
				}
				local_backend {
					method local
					path /etc/caddy/auth/local/users.json
					realm local
				}
			}
			ui {
				theme basic
				template login "/etc/caddy/theme/login.template"
				links {
					"WhoAmI" https://whoami.mydomain.com
					"LocalWhoAmI" /whoami
				}
			}
			transform user {
				match origin local
				action add role authp/user
			}
		}
		authorization policy test_policy {
			set auth url https://auth.mydomain.com
			crypto key verify <my-key>
			allow roles authp/admin authp/user
			validate bearer header
			inject header Remote-User from sub
			inject header "My-Roles" from roles
		}
	}
}
import snippets/*.conf
import sites/*.conf

Version Information

Provide output of caddy list-modules -versions | grep git below:

admin.api.load v2.4.6
admin.api.metrics v2.4.6
admin.api.reverse_proxy v2.4.6
caddy.adapters.caddyfile v2.4.6
caddy.config_loaders.http v2.4.6
caddy.listeners.tls v2.4.6
caddy.logging.encoders.console v2.4.6
caddy.logging.encoders.filter v2.4.6
caddy.logging.encoders.filter.delete v2.4.6
caddy.logging.encoders.filter.ip_mask v2.4.6
caddy.logging.encoders.filter.replace v2.4.6
caddy.logging.encoders.json v2.4.6
caddy.logging.encoders.single_field v2.4.6
caddy.logging.writers.discard v2.4.6
caddy.logging.writers.file v2.4.6
caddy.logging.writers.net v2.4.6
caddy.logging.writers.stderr v2.4.6
caddy.logging.writers.stdout v2.4.6
caddy.storage.file_system v2.4.6
http v2.4.6
http.authentication.hashes.bcrypt v2.4.6
http.authentication.hashes.scrypt v2.4.6
http.authentication.providers.http_basic v2.4.6
http.encoders.gzip v2.4.6
http.encoders.zstd v2.4.6
http.handlers.acme_server v2.4.6
http.handlers.authentication v2.4.6
http.handlers.encode v2.4.6
http.handlers.error v2.4.6
http.handlers.file_server v2.4.6
http.handlers.headers v2.4.6
http.handlers.map v2.4.6
http.handlers.metrics v2.4.6
http.handlers.push v2.4.6
http.handlers.request_body v2.4.6
http.handlers.reverse_proxy v2.4.6
http.handlers.rewrite v2.4.6
http.handlers.static_response v2.4.6
http.handlers.subroute v2.4.6
http.handlers.templates v2.4.6
http.handlers.vars v2.4.6
http.matchers.expression v2.4.6
http.matchers.file v2.4.6
http.matchers.header v2.4.6
http.matchers.header_regexp v2.4.6
http.matchers.host v2.4.6
http.matchers.method v2.4.6
http.matchers.not v2.4.6
http.matchers.path v2.4.6
http.matchers.path_regexp v2.4.6
http.matchers.protocol v2.4.6
http.matchers.query v2.4.6
http.matchers.remote_ip v2.4.6
http.matchers.vars v2.4.6
http.matchers.vars_regexp v2.4.6
http.precompressed.br v2.4.6
http.precompressed.gzip v2.4.6
http.precompressed.zstd v2.4.6
http.reverse_proxy.selection_policies.cookie v2.4.6
http.reverse_proxy.selection_policies.first v2.4.6
http.reverse_proxy.selection_policies.header v2.4.6
http.reverse_proxy.selection_policies.ip_hash v2.4.6
http.reverse_proxy.selection_policies.least_conn v2.4.6
http.reverse_proxy.selection_policies.random v2.4.6
http.reverse_proxy.selection_policies.random_choose v2.4.6
http.reverse_proxy.selection_policies.round_robin v2.4.6
http.reverse_proxy.selection_policies.uri_hash v2.4.6
http.reverse_proxy.transport.fastcgi v2.4.6
http.reverse_proxy.transport.http v2.4.6
pki v2.4.6
tls v2.4.6
tls.certificates.automate v2.4.6
tls.certificates.load_files v2.4.6
tls.certificates.load_folders v2.4.6
tls.certificates.load_pem v2.4.6
tls.certificates.load_storage v2.4.6
tls.handshake_match.remote_ip v2.4.6
tls.handshake_match.sni v2.4.6
tls.issuance.acme v2.4.6
tls.issuance.internal v2.4.6
tls.issuance.zerossl v2.4.6
tls.stek.distributed v2.4.6
tls.stek.standard v2.4.6

  Standard modules: 83

caddy.logging.encoders.filter.basic_auth_user v1.0.0
caddy.logging.encoders.formatted v0.0.0-20211204173940-c07f2a45108f
http.authentication.providers.authorizer v1.0.3
http.handlers.authenticator v1.0.3
http.handlers.trace v1.1.8
security v1.0.3

  Non-standard modules: 6

  Unknown modules: 0

Expected behavior

LDAP should work. Same LDAP config worked with old auth-portal.

feature: add shortcut and docs for oauth keycloak integration

A clear and concise description of what you want the system to do.

A clear and concise description of what you want the system to do.

  1. Create a shortcut for keyclock (similar to https://authp.github.io/docs/authenticate/misc#shortcuts)
  2. Document the integration in under https://github.com/authp/authp.github.io/tree/main/docs/authenticate/oauth
        generic_oauth2_backend {
          method oauth2
          realm generic
          provider generic
          client_id <id>
          client_secret <secret>
          scopes openid email profile
          base_auth_url https://<keycloak-url>
          metadata_url https://<keycloak-metadata-url>
        }

to:

keycloak <keycloak-url>

See https://github.com/greenpau/caddy-auth-portal/issues/215

question: How do roles work now

Previously utilizing caddy-authorize, this line for roles worked

allow roles User Admin

How would this be implemented in caddy-security, the docs don't seem to be updated yet. The repo's description includes this snippet,
allow roles authp/admin authp/user, but am unsure how to implement this in my existing Caddyfile, specifically I am using organizr's jwt, https://docs.organizr.app/features/server-authentication

feature: Issue PASETO tokens instead JWT by default #182

A clear and concise description of what you want the system to do.
Background

The Authenticator.grantAccess function is responsible for the issuing of signed
tokens to authenticated and authorized users. The function is also responsible
for the adding of sessions into the session cache.

The grantAccess issues an already generated token. It is being stored
in usr.Token.

The following functions invoke grantAccess():

  • Authenticator.authorizeLoginRequest(): pkg/authn/handle_http_login.go
  • Authenticator.handleHTTPSandbox(): pkg/authn/handle_http_sandbox.go

The authorizeLoginRequest():

  • takes in rr *requests.Request object. If it contains rr.Response.Payload
    with a map, then the associated authentication was processed successfully
  • creates user.User object from the map
  • passes newly created user.User object to be signed
    by p.keystore.SignToken()

The signing of tokens happens here in caddy-authorize.

The outstanding questions are:

  • What would be the Caddfile directive for setting up token encoding tech (JWT
    vs PASETO)?
  • When do you determine which token encoding tech would be issued? For example,
    what if a user transform says "set token tech to JWT"?

feature: LDAP support for GLAuth schema

Thank you for this awesome project, unfortunately I am having some issues with getting it to run with an LDAP backend:

Describe the issue

An attempt to log in over Caddy Security with an LDAP backend consisting of glauth-ui for management and glauth (https://github.com/glauth/glauth) as the LDAP provider fails with right credentials. The credentials were succesfully used by other means of connecting to glauth

Configuration

Paste full Caddyfile below:

(Domain names and unrelated services cut out)

{
  acme_ca https://acme-v02.api.letsencrypt.org/directory
  email   [...]
  debug

  security {
    authentication portal myportal {
      crypto default token lifetime 3600
      crypto key sign-verify [...]
       
      backends {
        ldap_backend {
          method ldap
          realm [...]
          servers {
            ldap://login_system_glauth_1:389 ignore_cert_errors posix_groups
          }
          attributes {
            name givenname
            surname sn
            username name
            #member_of primarygroup #memberOf
            email mail
          }
          username "CN=[...],DC=[...],DC=[...],OU=[...]"
          password "[...]"
          search_base_dn "DC=[...],DC=[...],OU=[...]"
          search_filter "(|(name=%s)(mail=%s))"
          groups {
            "CN=people,OU=[...],DC=[...],DC=[...]" people
            "CN=5501,OU=[...],DC=[...],DC=[...]" people2
          }
        }
      }

      cookie domain [...]
      ui {
        links {
          "My Website (super secret)" [...]/foo
          "My Identity" "/whoami"
        }
      }
    }

    authorization policy mypolicy {
      set auth url /auth/
      crypto key sign-verify [...]
      allow roles people people2
    }
  }
}

[...]:443/* {
  #Protected super secret part of website
  redir /foo /foo/
  handle_path /foo/* {
    route {
      authorize with mypolicy
    }
    respond * "foobar website" 200
  }

  handle {
    route /auth* {
      authenticate * with myportal
    }

    #unprotected landing page
    reverse_proxy nginx:80
  }
}

Version Information

Provide output of caddy list-modules -versions | grep git below:

Caddy version is v2.4.6 running in docker. Above command yields no results with grep git. Without it it looks like

[...] 

  Standard modules: 83

http.authentication.providers.authorizer v1.0.6
http.handlers.authenticator v1.0.6
security v1.0.6

  Non-standard modules: 3

  Unknown modules: 0

Expected behavior

A successful login

Additional context

Caddy logs:

[Note: User entry follows]
caddy_1  | {"level":"debug","ts":1643228260.8880885,"logger":"security","msg":"LDAP dialer setup succeeded","server":"ldap://login_system_glauth_1:389"}
caddy_1  | {"level":"debug","ts":1643228260.8909764,"logger":"security","msg":"LDAP binding succeeded","server":"ldap://login_system_glauth_1:389"}
caddy_1  | {"level":"debug","ts":1643228260.8923666,"logger":"security","msg":"LDAP search succeeded","server":"ldap://login_system_glauth_1:389","entry_count":0,"search_base_dn":"DC=[...],DC=DE,OU=[...]","search_user_filter":"(|(name=[foo])(mail=[foo]))","users":[]}
caddy_1  | {"level":"debug","ts":1643228260.9456468,"logger":"security","msg":"user authorization sandbox","sandbox_id":"AGrfuqfC377A6TzZYt6mYPFlKR9gK3YF8b93QH11stXLMh","sandbox_secret":"Edtvxjl3AIukviHXjEjstxPimZRzFRgEdQgjKUPU","sandbox_partition":"","checkpoints":[{"name":"Authenticate with password","type":"password"}]}
caddy_1  | {"level":"debug","ts":1643228260.9464517,"logger":"security","msg":"next user authorization checkpoint","session_id":"pAJ0OR8hQL5NuWH0638JbOpq7JozxxTp6zfjm7","request_id":"5ce045e3-cdb6-4c07-8940-a615318dca25","data":{"action":"auth","title":"Password Authentication","view":"password_auth"}}

[Note: Password entry]
caddy_1  | {"level":"debug","ts":1643228269.0140665,"logger":"security","msg":"user authorization sandbox","sandbox_id":"AGrfuqfC377A6TzZYt6mYPFlKR9gK3YF8b93QH11stXLMh","sandbox_secret":"Edtvxjl3AIukviHXjEjstxPimZRzFRgEdQgjKUPU","sandbox_partition":"password-auth","checkpoints":[{"name":"Authenticate with password","type":"password"}]}
caddy_1  | {"level":"debug","ts":1643228269.0155284,"logger":"security","msg":"LDAP dialer setup succeeded","server":"ldap://login_system_glauth_1:389"}
caddy_1  | {"level":"debug","ts":1643228269.01613,"logger":"security","msg":"LDAP binding succeeded","server":"ldap://login_system_glauth_1:389"}
caddy_1  | {"level":"warn","ts":1643228269.0173078,"logger":"security","msg":"user authorization checkpoint failed","session_id":"pAJ0OR8hQL5NuWH0638JbOpq7JozxxTp6zfjm7","request_id":"3a4848b6-9f80-47c5-bca7-e8bab3a71cf2","error":"Password authentication failed. Please retry"}

Structure of glauth users:

  name = "fbar"
  givenname = "foo
  sn = "bar"
  mail = "[email protected]"
  unixid = 5003
  primarygroup = 5501
  passsha256 = "foofoobarbar"
  otherGroups = [ 5551 ]

glauth output:

glauth_1      | 19:45:40.200821 Bind โ–ถ DEBU 025  "level"=6 "msg"="Bind request"  "basedn"="dc=[...],dc=de,ou=[...]" "binddn"="cn=[management user specified in Caddyfile],dc=[...],dc=de,ou=[...]" "src"={"IP":"172.28.0.7","Port":38570,"Zone":""}
glauth_1      | 19:45:40.201705 Bind โ–ถ DEBU 026  "level"=6 "msg"="Bind success"  "binddn"="cn=[management user specified in Caddyfile],dc=[...],dc=de,ou=[...]" "src"={"IP":"172.28.0.7","Port":38570,"Zone":""}
glauth_1      | 19:45:40.202217 Search โ–ถ DEBU 027  "level"=6 "msg"="Search request"  "basedn"="dc=[...],dc=de,ou=[...]" "binddn"="cn=[management user specified in Caddyfile],dc=[...],dc=de,ou=[...]" "filter"="(|(name=[foo])(mail=[foo]))" "scope"=2 "searchbasedn"="dc=[...],dc=de,ou=[...]" "src"={"IP":"172.28.0.7","Port":38570,"Zone":""}
glauth_1      | 19:45:40.203287 Search โ–ถ DEBU 028  "level"=6 "msg"="AP: Search OK"  "filter"="(|(name=[foo])(mail=[foo]))"
glauth_1      | 19:45:44.544377 Bind โ–ถ DEBU 029  "level"=6 "msg"="Bind request"  "basedn"="dc=[...],dc=de,ou=[...]" "binddn"="cn=[management user specified in Caddyfile],dc=[...],dc=de,ou=[...]" "src"={"IP":"172.28.0.7","Port":38572,"Zone":""}
glauth_1      | 19:45:44.544462 Bind โ–ถ DEBU 02a  "level"=6 "msg"="Bind success"  "binddn"="cn=[management user specified in Caddyfile],dc=[...],dc=de,ou=[...]" "src"={"IP":"172.28.0.7","Port":38572,"Zone":""}
glauth_1      | 19:45:44.544891 Search โ–ถ DEBU 02b  "level"=6 "msg"="Search request"  "basedn"="dc=[...],dc=de,ou=[...]" "binddn"="cn=[management user specified in Caddyfile],dc=[...],dc=de,ou=[...]" "filter"="(|(name=nobody)(mail=nobody))" "scope"=2 "searchbasedn"="dc=[...],dc=de,ou=[...]" "src"={"IP":"172.28.0.7","Port":38572,"Zone":""}
glauth_1      | 19:45:44.545011 Search โ–ถ DEBU 02c  "level"=6 "msg"="AP: Search OK"  "filter"="(|(name=nobody)(mail=nobody))"

feature: snippets in caddy security configuration

With the previous caddy-auth-portal and caddy-auth-jwt it was possible to setup a portal per-domain in separate files. This ability was useful to me since I use one Caddy instance to serve many apps, each with their own OAuth2 endpoint in my SSO. I've designed my Caddy config with one main Caddyfile that imports a directory of additional per-app Caddyfiles like so:

// Main Caddyfile
(sso) {
    route /auth* {
        authp {
            backends {
                generic_oauth2_backend {
                    method oauth2
                    realm ml
                    provider generic
                    metadata_url https://sso.somewhere.com/{args.0}
                    base_auth_url https://sso.somewhere.com/
                    client_id "{args.1}"
                    client_secret "{args.2}"
                    scopes openid email profile
                }
            }
        }
    }
}

(sso-jwt) {
    jwt {
        primary yes
        set auth url /auth/oauth2/ml
        allow roles authp/admin authp/user authp/guest
        inject headers with claims
    }
}

import ./apps/*.caddy

// Site Caddyfile
some.place.com {
	import sso some_place ID SECRET
	route {
		import sso-jwt
		reverse_proxy 10.1.0.5:8028 {
			// ...
		}
	}
}

From what I can tell with the new caddy-security (and please correct me if I'm wrong), the only way to setup auth "portals" is now via the global config and I can't configure any portals via my included files (since Caddy doesn't allow multiple globals blocks).

Is there any way to still use the above (or similar) file architecture with the new design of caddy-security?

Thanks for the project and taking a look at this question!

feature: throttle sandbox authentication requests

A clear and concise description of what you want the system to do.

Implement controls against:

  1. Password spray attack (track by source IP address)
  2. Password brute-force attack (track by user identity)

Upon the detection of the above attack, the offending IP/identity should be blocked for a period of time, e.g. 15 minutes.

Record username and source IP address.

  • Block source IP address that failed auth 10+ times within 2 minute period across multiple usernames
  • Block username who failed auth 5+ times within 5 minute period having same source IP address

Azure Claims add to JWT for Caddy Security

After parsing the through the logs and the tokens with @greenpau we have determined that it is doable to add extra claims from AzureAD to the token from Caddy Security.

The access token generated from Azure:

{
  "aud": "",
  "iss": "",
  "iat": 1642521327,
  "nbf": 1642521327,
  "exp": 1642526598,
  "acct": 0,
  "acr": "1",
  "aio": "",
  "amr": [
    "pwd",
    "mfa"
  ],
  "app_displayname": "Caddy",
  "appid": "",
  "appidacr": "1",
  "family_name": "",
  "given_name": "",
  "idtyp": "user",
  "ipaddr": "WHELPIGUESSIPOSTEDMYIPHERE",
  "name": "FIRSTNAME LASTNAME",
  "oid": "THISISWHATIWANT",
  "onprem_sid": "",
  "platf": "5",
  "puid": "",
  "rh": "",
  "scp": "email openid profile User.Read User.Read.All",
  "signin_state": [
    "kmsi"
  ],
  "sub": "",
  "tenant_region_scope": "NA",
  "tid": "",
  "unique_name": "email",
  "upn": "email",
  "uti": "",
  "ver": "1.0",
  "wids": [

  ],
  "xms_st": {
    "sub": ""
  },
  "xms_tcdt": 
}

The ID Token from Azure:

{
  "aud": "",
  "iss": "https://login.microsoftonline.com/TENANTID/v2.0",
  "iat": 1642521327,
  "nbf": 1642521327,
  "exp": 1642525227,
  "email": "EMAIL",
  "family_name": "LASTNAME",
  "name": "FIRSTNAME LASTNAME",
  "nonce": "",
  "oid": "THISISWHATIWANTHERE",
  "preferred_username": "EMAILADDRESS",
  "rh": "",
  "roles": [
    "admin",
    "user",
    "guest"
  ],
  "sub": "",
  "tid": "",
  "upn": "",
  "uti": "",
  "ver": "2.0"
}

Logs receiving OAUTH 2.0 Authorization:

{"level":"debug","ts":1642521627.4824917,"logger":"http.handlers.authp","msg":"received OAuth 2.0 authorization server access token","request_id":"30b02156-b7dc-430a-ac96-f23d7903dc23","token":{"access_token":"SEEACCESSTOKENCLAIMABOVE","expires_in":4970,"ext_expires_in":4970,"id_token":"SEEIDTOKENABOVE","scope":"email openid profile User.Read User.Read.All","token_type":"Bearer"}}

Logs containing decoded claims from OAUTH server access token:

{"level":"debug","ts":1642521627.483103,"logger":"http.handlers.authp","msg":"decoded claims from OAuth 2.0 authorization server access token","request_id":"30b02156-b7dc-430a-ac96-f23d7903dc23","claims":{"email":"EMAIL","exp":1642525227,"iat":1642521327,"iss":"https://login.microsoftonline.com/TENANTID/v2.0","name":"FIRSTNAME LASTNAME","roles":["admin","user", "guest"],"sub":""}}

question: x509 authentication

First, but unrelated to the topic, thank you for all of your amazing projects. I recently came across the thread which inspired you to write caddy-git, and your candor and contributions to the community are such a breath of fresh air.

Back on topic :)

I came across the x509 authp document which has a TODO. Which I wasn't sure if it was a TODO to write the documentation or the implementation and documentation.

I checked into the go-authcrunch (btw, I love the split from the original auth-portal..I love the fact that it could be included with my Gin projects โค๏ธโ€๐Ÿ”ฅ) and I couldn't find any implementations for x509 auth.

I'm in the planning phase for a project, for which x509 auth with caddy-security would be a wonderful fit.

I was curious if the ldap backend would be a good place for me to to start with writing a x509 implementation. I would love to contribute any work back (if we go this route), but I wanted to see if you had any previous requirements, hurdles or issues with an x509 backend that I could keep into consideration when contributing back.

question: Help transitioning from caddy-auth-portal to caddy-security

Working to get converted from caddy-auth-portal to caddy-security. I have a new docker image and Caddyfile. I am able to go to http://192.168.1.106 and am returned "Client sent an HTTP request to an HTTPS server". Good sign caddy is listening on port 80. When I go to https://192.168.1.106/auth or https://192.168.1.106/portainer I get "This site canโ€™t provide a secure connection". I am not seeing any errors in the logs. Not sure what I am missing.

Version

docker exec -it caddy /bin/sh -c "caddy list-modules -versions | grep security"
security v1.0.13

Caddyfile

{
	debug
	https_port	80
	http_port	        443
	local_certs

	security {
		credentials smtp.contoso.com {
			username foo
			password bar
			domain contoso.com
		}

		authentication portal myportal {
			cookie lifetime 86400
			crypto default token lifetime 3600
			crypto key sign-verify <redacted>
			backend local /config/caddy/users.json local
			ui {
				links {
					"Portainer" "/portainer" icon "las la-star"
					"My Identity" "/auth/whoami" icon "las la-user"
				}
			}
			transform user {
				match origin local
				action add role authp/user
				ui link "Portal Settings" /auth/settings icon "las la-cog"
			}
		}

		authorization policy mypolicy {
			set auth url /auth/
			crypto key verify <redacted>
			allow roles authp/admin authp/user
		}
	}
}

192.168.1.106, 127.0.0.1, localhost {
	route /version* {
		respond * "1.0.0" 200
	}

	route /auth* {
		authenticate * with myportal
	}

	route /xauth* {
		authenticate * with myportal
	}

	route /portainer/* {
		authorize with mypolicy
		reverse_proxy 192.168.1.106:9000
	}

	route {
		redir https://{hostport}/auth 302
	}
}

Dockerfile

ARG CADDY_VERSION=2.4.6

FROM caddy:${CADDY_VERSION}-builder AS builder

RUN xcaddy build \
    --with github.com/lucaslorentz/caddy-docker-proxy/plugin/v2 \
    --with github.com/greenpau/caddy-security \
    --with github.com/greenpau/caddy-trace \
	--with github.com/porech/caddy-maxmind-geolocation \
	--with github.com/caddy-dns/cloudflare \
	--with github.com/kirsch33/realip

FROM caddy:${CADDY_VERSION}-alpine

# Timezone
ENV TIMEZONE America/Chicago

# Install timezone data and setup timezone
RUN apk --update add --no-cache --virtual .tz-deps tzdata \
    && cp /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
    && echo ${TIMEZONE} > /etc/timezone \
    && apk del .tz-deps

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

CMD ["caddy", "docker-proxy"]

Caddy Logs

{"level":"info","ts":1644499353.9904323,"logger":"http.handlers.authenticator","msg":"validated authenticator","portal_name":"myportal","portal_id":"f375cf79-c7e6-42e6-a02a-a33d07113777","path":"*","id":"e9adc199-52b5-4649-a0b6-14837dd8bd85"}
{"level":"info","ts":1644499353.998644,"logger":"pki.ca.local","msg":"root certificate is already trusted by system","path":"storage:pki/authorities/local/root.crt"}
{"level":"debug","ts":1644499353.9987516,"logger":"security","msg":"starting app instance","app":"security"}
{"level":"debug","ts":1644499353.998758,"logger":"security","msg":"started app instance","app":"security"}
{"level":"debug","ts":1644499353.9988534,"logger":"http","msg":"starting server loop","address":"[::]:80","http3":false,"tls":true}
{"level":"debug","ts":1644499353.9989147,"logger":"http","msg":"starting server loop","address":"[::]:443","http3":false,"tls":false}
{"level":"info","ts":1644499353.998918,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["192.168.1.106","127.0.0.1","localhost"]}
{"level":"info","ts":1644499353.9989662,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
{"level":"info","ts":1644499353.9995062,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"warn","ts":1644499353.999512,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [192.168.1.106]: no OCSP server specified in certificate"}
{"level":"debug","ts":1644499353.9995527,"logger":"tls.cache","msg":"added certificate to cache","subjects":["192.168.1.106"],"expiration":1644541671,"managed":true,"issuer_key":"local","hash":"a616768686a916945332dfc420f5fc7149ea6d967e4ff05979cca3af67dbb1d0","cache_size":1,"cache_capacity":10000}
{"level":"warn","ts":1644499353.999942,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [127.0.0.1]: no OCSP server specified in certificate"}
{"level":"debug","ts":1644499353.9999826,"logger":"tls.cache","msg":"added certificate to cache","subjects":["127.0.0.1"],"expiration":1644541564,"managed":true,"issuer_key":"local","hash":"f6d0146c2e8582b7398d38326853364c47a137adb6a56716ececbc478e31117c","cache_size":2,"cache_capacity":10000}
{"level":"warn","ts":1644499354.000346,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [localhost]: no OCSP server specified in certificate"}
{"level":"debug","ts":1644499354.0003831,"logger":"tls.cache","msg":"added certificate to cache","subjects":["localhost"],"expiration":1644541564,"managed":true,"issuer_key":"local","hash":"d36df32c8163a53370c558c82aa9e7876da1e5b3faa3c1ebf85888810093e3c2","cache_size":3,"cache_capacity":10000}
{"level":"info","ts":1644499354.000548,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1644499354.0006375,"logger":"admin.api","msg":"load complete"}
{"level":"info","ts":1644499354.000823,"logger":"docker-proxy","msg":"Successfully configured","server":"localhost"}
{"level":"info","ts":1644499354.0030348,"logger":"admin","msg":"stopped previous server","address":"tcp/localhost:2019"}{"level":"info","ts":1644499354.0676877,"logger":"docker-proxy","msg":"Skipping swarm config caddyfiles because swarm is not available"}
{"level":"info","ts":1644499354.0692687,"logger":"docker-proxy","msg":"Skipping swarm services because swarm is not available"}
{"level":"info","ts":1644499384.0679076,"logger":"docker-proxy","msg":"Skipping swarm config caddyfiles because swarm is not available"}

question: how to setup basic authentication

A clear and concise description of what you want to accomplish.

Hi, i have few services which I need to put behind authentication.

Could you please provide a snippet how can I add the basic authentication to one of my service.

Thank you

feature: iOS/Android App Authentication

A clear and concise description of what you want the system to do.

  1. User opens iOS app and the user is not authenticated
  2. iOS app generates a random code (100+ characters long) called dropbox_code
  3. iOS app must support UniversalLinks
  4. iOS app opens a browser to http://<auth_portal_base_url>/login?otp_code=<random-code>&app_link=<universal_link>
  5. The user authenticates in the browser. When authenticated, the browser opens a link to iOS app
  6. The iOS app calls http://<auth_portal_base_url>/otp?code=<random-code> and received JWT token that could be used to access API endpoints. The app can access the OTP endpoint with the code only once. The portal destroy the after a user accesses it.

breakfix: Access token set without expiry, still gets 401, and doesn't redirect to provided auth url

Describe the issue

After logging in at https://auth.MYDOMAIN.com, the auth portal sets a cookie without a Max-Age or expires attribute set, meaning it only lives as long as the session. Example set-cookie header in the response of /oauth2/github/authorization-code-callback?code=OAUTH_CODE... after logging in with github:

set-cookie: access_token=eyJhbGciOiJI....; Domain=MYDOMAIN.com; Path=/; Secure; HttpOnly;

Also, the access token itself doesn't seem to work at all with my current configuration, and I get a 401 on the example domain of this config https://sonarr.MYDOMAIN.com, with error logs like:

{"level":"debug","ts":1642792571.8178122,"logger":"security","msg":"token validation error","session_id":"cO9Fu3cuNuNg5ufIugXgZphXU5MSzEFhfByBX0ojPb8","request_id":"26a2f6a9-51fb-4be8-92ac-85f40eefbfd5","error":"token validator: invalid token: keystore: failed to parse token"}
{"level":"error","ts":1642792571.8178322,"logger":"http.handlers.authentication","msg":"auth provider returned error","provider":"authorizer","error":"user authorization failed"}

and it just redirects to https://sonarr.MYDOMAIN.com/?redirect_url=https%3A%2F%2Fsonarr.MYDOMAIN.com%2F, rather than redirecting to https://auth.MYDOMAIN.com as I'd expect.

My very very similar config previously using caddy-authorize and caddy-auth-portal worked fine, I've basically just moved around the attributes to be inline with how the new config format looks, and I used the jumpcloud config as my example.

Configuration

{
        debug
        order authorize before basicauth
        email {$CF_EMAIL}
        auto_https ignore_loaded_certs

        security {
                authentication portal mainportal {
                        crypto default token lifetime 2419200
                        crypto key sign-verify {$CADDY_AUTH_TOKEN_SECRET}
                        cookie domain {$DOMAIN}
                        backend local {$CADDY_AUTH_USERS_PATH} local
                        backend github {$CADDY_GITHUB_OAUTH_CLIENT_ID} {$CADDY_GITHUB_OAUTH_CLIENT_SECRET}
                        transform user {
                                exact match sub github.com/johnpyp
                                action add role authp/admin
                                action add role superadmin
                        }
                        transform user {
                                match email [email protected]

                                action add role authp/admin
                                action add role superadmin
                        }
                }

                authorization policy mainpolicy {
                        set auth url https://auth.{$DOMAIN}
                        allow roles admin superadmin authp/admin
                        crypto key verify {$CADDY_AUTH_TOKEN_SECRET}
                }
        }
}

(cf_tls) {
        tls {
                issuer zerossl {
                        resolvers 1.1.1.1
                        dns cloudflare {$CF_API_TOKEN}
                }
        }
}

auth.{$DOMAIN} {
        import cf_tls
        route {
                authenticate * with mainportal
        }
}

(protected_route) {
        {args.0}.{$DOMAIN} {
                import cf_tls
                authorize with mainpolicy
                route {
                        reverse_proxy {args.1}
                }
        }
}

import protected_route sonarr sonarr:8989
// ...

Version Information

Should be latest everything, just pulled a few minutes ago with this docker image:

FROM caddy:2-builder AS builder

RUN xcaddy build \
    --with github.com/greenpau/caddy-security \
    --with github.com/caddy-dns/cloudflare

FROM caddy:2

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

feature: negative matches

I want to be able to handle inverse matching in transforms.

  1. If email field exists in the data, and it does not match, the condition is satisfied and the authp/test role gets added.
    If the field does NOT exist, then it is also a match!
      transform user {
        no suffix match email @contoso.com if exists
        action add role authp/test
      }
  1. The condition is NOT satisfied when any:
  • email field does not exists in the data
  • the value of the email field matches
      transform user {
        no suffix match email @contoso.com
        action add role authp/test
      }

Original issue: https://github.com/greenpau/caddy-authorize/issues/80

breakfix: Caddy fails with `messaging provider config "sender_email" key is empty` after trying to update config for 1.0.10

Describe the issue

Before update 1.0.10, my configuration was working fine, but now it throws this error:

{"level":"info","ts":1643574293.9224517,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
run: adapting config using caddyfile: parsing caddyfile tokens for 'security': /etc/caddy/Caddyfile:7 - Error during parsing: Wrong argument count or unexpected line ending after 'smtp.sendgrid.net'
{"level":"info","ts":1643574296.3687108,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
run: adapting config using caddyfile: parsing caddyfile tokens for 'security': /etc/caddy/Caddyfile:7 - Error during parsing: Wrong argument count or unexpected line ending after 'smtp.sendgrid.net'

I didn't see anything about this in the update notes, but I tried to adapt my configuration file to what seemed like two new sections in the README, this and this. I thought I fixed it, but now it's throwing this error:

{"level":"info","ts":1643574464.2447708,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
run: adapting config using caddyfile: parsing caddyfile tokens for 'security': malformed ["security.messaging" "email" "provider"] directive: messaging provider config "sender_email" key is empty
{"level":"info","ts":1643574467.0772052,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
run: adapting config using caddyfile: parsing caddyfile tokens for 'security': malformed ["security.messaging" "email" "provider"] directive: messaging provider config "sender_email" key is empty

Configuration

Paste full Caddyfile below:

{ # Global configuration
    order authenticate first
    order authorize before reverse_proxy
    acme_dns cloudflare REDACTED
    email REDACTED
    security {
        credentials smtp.sendgrid.net {
            username {env.SMTP_USERNAME}
            password {env.SMTP_PASSWORD}
        }
        messaging email provider smtp.sendgrid.net {
            address smtp.sendgrid.net:587
            protocol smtp
            credentials smtp.sendgrid.net
        }
        authentication portal myportal {
            backend local /etc/caddy/auth/local/users.json local
                    cookie domain haddock.cc
            crypto key sign-verify REDACTED
            crypto default token lifetime 86400
            cookie lifetime 172800
            ui {
                links { # Icons here -> https://icons8.com/line-awesome
                    "Cloud" https://cloud.haddock.cc icon "las la-cloud"
                    "Media" https://media.haddock.cc icon "las la-photo-video"
                    "Get TV Shows" https://tv.haddock.cc icon "las la-tv"
                    "Get Movies" https://movies.haddock.cc icon "las la-video"
                }
            }
            transform user {
                match origin local
                action add role authp/user
                ui link "Portal Settings" /settings icon "las la-cog"
            }
        }
        authorization policy mypolicy {
            set auth url https://auth.haddock.cc/
            crypto key verify REDACTED
            allow roles authp/admin authp/user
        }
    }
}

auth.haddock.cc { # Auth portal
    authenticate with myportal
}

cloud.haddock.cc {
    authorize with mypolicy
    encode zstd
    reverse_proxy nextcloud:80 {
        header_down Strict-Transport-Security "max-age=15552000; includeSubDomains"
        header_down X-Content-Type-Options "nosniff"
        header_down X-XSS-Protection "1; mode=block"
        header_down X-Robots-Tag "none"
        header_down X-Frame-Options "SAMEORIGIN"
        header_down Referrer-Policy "no-referrer"
    }
    rewrite /.well-known/carddav /remote.php/dav
    rewrite /.well-known/caldav /remote.php/dav
}

media.haddock.cc {
    authorize with mypolicy
    reverse_proxy jellyfin:8096
}

prowl.haddock.cc { # Prowlarr
    authorize with mypolicy
    reverse_proxy prowlarr:9696
}

tv.haddock.cc { # Sonarr
    authorize with mypolicy
    reverse_proxy sonarr:8989
}

movies.haddock.cc { # Radarr
    authorize with mypolicy
    reverse_proxy radarr:7878
}

guard.haddock.cc { # AdGuard Home
    authorize with mypolicy
    reverse_proxy adguard:80
}

localhost:8112 { # QBittorrent
    reverse_proxy torrent:8080
}

Version Information

Provide output of caddy list-modules -versions | grep git below:

dns.providers.cloudflare v0.0.0-20210607183747-91cf700356a1
http.authentication.providers.authorizer v1.0.10
http.handlers.authenticator v1.0.10
security v1.0.10

Expected behavior
Caddy doesn't crash.

breakfix: Token used before issued

Describe the issue

This is my first time using Caddy for any project. I am attempting to provide Google authentication to internal websites. I started a few days ago with caddy-auth-portal and today I converted it to caddy-security. However, on both versions, I randomly get the error:

"failed validating OAuth 2.0 access token: OAuth 2.0 failed to parse id_token: Token used before issued"

This results in an "Unauthorized" response from the login portal.

If you sign into the portal, and then click the "logout" button, when you sign in again it will often give you the error the second time.

Some Googling provides this link to a discussion about "clock skew":
dgrijalva/jwt-go#383

Client and server are synchronized and no more than a fraction of a second different so I'm not sure if that is the problem.

Configuration

{
    debug
    order authorize before reverse_proxy
    order authenticate before authorize

	security {
		authentication portal myportal {
			backend google <redacted>.apps.googleusercontent.com <redacted>
			ui {
				links {
					"My Identity" "/auth/whoami" icon "las la-star"
				}
			}
			transform user {
				match origin google
				suffix match email @my.domain
				action add role authp/user
				ui link "Application" "https://app.my.domain/secure"
			}
			transform user {
#not sure if "exact match" is appropriate here, but was based on examples
				exact match origin google
				exact match email [email protected]
				action add role authp/admin
			}
			cookie domain my.domain
		}
		authorization policy mypolicy {
			set auth url /auth/oauth2/google
			allow roles authp/admin authp/user
		}		
	}
}

auth.my.domain {
	route /auth* {
		authenticate * with myportal
	}
}	

app.my.domain {
	route /secure* {
		authorize with mypolicy
		reverse_proxy https://app.mydomain
	}
	route {
		reverse_proxy https://app.mydomain
	}
}

Version Information

Windows version of Caddy built this morning from the download page with only caddy-security included.

Expected behavior

Should authenticate as normal without error.

Additional context

Caddy is running on Windows.

feature: add IP logging to failed password login attempts

A clear and concise description of what you want the system to do.

"Password authentication failed. Please retry" error should also log the IP, not just the session_id/request_id, to allow software like Fail2Ban to work against brute force attackers.

question: Email setup

Trying to get email working for user registration. I do not see any errors in the logs, but get email error when a user tries to register. Below is the relevant config I am using. Guessing I don't quite have the config correct, but not sure what I am missing.

	security {
		credentials [email protected] {
			username [email protected]
			password <app_passowrd>
		}
		messaging email provider gmail {
			address smtp.gmail.com:587
			protocol smtp
			credentials [email protected]
			sender [email protected] "My Auth Portal"
		}
		authentication portal myportal {
			enable source ip tracking
			cookie lifetime 86400
			crypto default token lifetime 3600
			crypto key sign-verify <redacted>
			cookie domain mydomain.net
			backend local /config/caddy/users.json local
			transform user {
				match roles registered
				require mfa
			}
			registration {
				dropbox /config/caddy/registrations.json
				title "User Registration"
				code "Test"
				require domain mx
				email provider gmail
			}
...

What JWKS key types are supported in the generic OAuth2 backend?

New to Caddy, new to OAuth & OIDC so brace yourselves. I'm trying to add OAuth/OIDC authentication to a site. I'm using this config file as a reference. Things are going ok to start with, here's where (I think) I'm at:

  1. It looks like Caddy is hitting my metadata_url and finding the jwks_uri field.
  2. Once it hits the jwks_uri, it appears to be reading the first key in the array whose kty (key type) is EC.
  3. Then I get this message and exit with code 1:

provision security: backend configuration for "myportal" portal failed: failed to fetch jwt keys for OAuth 2.0 authorization server: invalid jwks key: unsupported key type EC for <my_key>

where <my_key> is the EC key found at the jwks_uri. So my questions are:

  1. Is the EC kty (keytype) supported?
  2. If not, can I direct Caddy to use another key from the jwks_uri?
  3. Have I misunderstood this completely?

caddy reload gives an error

Describe the issue

Using now caddy-security. It starts fine, but I get this error after caddy reload.

reload: sending configuration to instance: caddy responded with error: HTTP 400: {"error":"loading config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 18: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 2: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'authentication': provision http.handlers.authentication: loading authentication providers: module name 'authorizer': provision http.authentication.providers.authorizer: loading security app module: provision security: authentication portal \"myportal\" already registered"}

Configuration

Caddyfile

{
	servers :443 {
		protocol {
			experimental_http3
		}
	}
	servers :8448 {
		protocol {
			experimental_http3
		}
	}
	#debug
	admin :2019 {
		origins 192.168.170.2
	}

	security {
		authentication portal myportal {
			crypto default token lifetime 120
			crypto key sign-verify <my-key>
			cookie domain mydomain.com
			backends {
				local_backend {
					method local
					path /etc/caddy/auth/local/users.json
					realm local
				}
			}
			ui {
				theme basic
				template login "/etc/caddy/theme/login.template"
				links {
					"WhoAmI" https://whoami.mydomain.com
					"LocalWhoAmI" /whoami
				}
			}
			transform user {
				match origin local
				action add role authp/user
			}
		}
		authorization policy test_policy {
			set auth url https://auth.mydomain.com
			crypto key verify <my-key>
			allow roles authp/admin authp/user
			validate bearer header
			inject header Remote-User from sub
			inject header "My-Roles" from roles
		}
	}
}
import snippets/*.conf
import sites/*.conf

auth.conf

auth.mydomain.com:443 {
	import wildcard
	import client_headers
	import log_formatted INFO

	route {
		authenticate * with myportal
	}
}

whoami.conf

whoami.mydomain.com:443 {
	import wildcard
	import client_headers
	import log_formatted INFO

	route {
		authorize with test_policy
		reverse_proxy http://192.168.170.2:8000 {
			import backend_headers 443
		}
	}

Version Information

Caddy 2.4.6

Expected behavior

No errors :)

Reload users.json

Hey! I was wondering if it is possible to add users to the local backend and have them be able to be authenticated by auth portal at once without having to stop and start the caddy process. Thanks for the great plugin ๐Ÿ‘

feature: add password reset link

A clear and concise description of what you want the system to do.

An administrator may allow a user to reset the password. For that purpose, the admin will create a one-time use link, the user would follow for the password reset.

Using GitHub auth, I keep getting "error = Redirect_URI Mismatch" after using the github portal.

Describe the issue

I have no idea how to properly configure a call-back URL. I keep getting the same error over and over. I replaced my personal domain with example.com.

image

https://auth.example.com/auth/oauth2/github?error=redirect_uri_mismatch&error_description=**The+redirect_uri+MUST+match+the+registered+callback+URL+for+this+application.**&error_uri=https%3A%2F%2Fdocs.github.com%2Fapps%2Fmanaging-oauth-apps%2Ftroubleshooting-authorization-request-errors%2F%23redirect-uri-mismatch&state={randomnumbers}

I have tried different combinations of callurls in the github app configuration but I get no success. And I get the same error represented in the URL and screenshot no matter what combination I try.

image

Configuration

Paste full Caddyfile below:

{
	http_port 8080
	https_port 8443

	order authenticate before respond
	order authorize before basicauth

	security {
		authentication portal myportal {
			crypto default token lifetime 3600
			backend github {env.GOOGLE_CLIENT_ID} {env.GOOGLE_CLIENT_SECRET}
			cookie domain example.com
			ui {
				links {
					"My Identity" "/whoami" icon "las la-user"
				}
			}

			transform user {
				match realm github
				action add role authp/user
				match sub github.com/githubuser1 github.com/githubuser2 #Side question: Is this how you limit github login to only certain users?
				ui link "File Server" https://assetq.example.com:8443/ icon "las la-star"
			}

			transform user {
				match realm github
				match sub github.com/rubydotexe
				action add role authp/admin
			}
		}

		authorization policy mypolicy {
			set auth url https://auth.example.com:8443/auth/oauth2/github
			allow roles authp/admin authp/user 
			validate bearer header
			inject headers with claims
		}
	}
}

(tls_config) {
	tls  /home/caddy/.local/certbot/live/example.com-0001/fullchain.pem /home/caddy/.local/certbot/live/example.com-0001/privkey.pem
}

*.example.com {
    tls /home/caddy/.local/certbot/live/example.com/fullchain.pem /home/caddy/.local/certbot/live/example.com/privkey.pem
}

auth.example.com {
	import tls_config
	authenticate with myportal
}

assetq.example.com {
	import tls_config
	authorize with mypolicy
	root * {env.HOME}/www
	file_server
}

Version Information

Provide output of caddy list-modules -versions | grep git below:
(The terminal displayed nothing if I included grep git)

admin.api.load v2.4.6
admin.api.metrics v2.4.6
admin.api.reverse_proxy v2.4.6
caddy.adapters.caddyfile v2.4.6
caddy.config_loaders.http v2.4.6
caddy.listeners.tls v2.4.6
caddy.logging.encoders.console v2.4.6
caddy.logging.encoders.filter v2.4.6
caddy.logging.encoders.filter.delete v2.4.6
caddy.logging.encoders.filter.ip_mask v2.4.6
caddy.logging.encoders.filter.replace v2.4.6
caddy.logging.encoders.json v2.4.6
caddy.logging.encoders.single_field v2.4.6
caddy.logging.writers.discard v2.4.6
caddy.logging.writers.file v2.4.6
caddy.logging.writers.net v2.4.6
caddy.logging.writers.stderr v2.4.6
caddy.logging.writers.stdout v2.4.6
caddy.storage.file_system v2.4.6
http v2.4.6
http.authentication.hashes.bcrypt v2.4.6
http.authentication.hashes.scrypt v2.4.6
http.authentication.providers.http_basic v2.4.6
http.encoders.gzip v2.4.6
http.encoders.zstd v2.4.6
http.handlers.acme_server v2.4.6
http.handlers.authentication v2.4.6
http.handlers.encode v2.4.6
http.handlers.error v2.4.6
http.handlers.file_server v2.4.6
http.handlers.headers v2.4.6
http.handlers.map v2.4.6
http.handlers.metrics v2.4.6
http.handlers.push v2.4.6
http.handlers.request_body v2.4.6
http.handlers.reverse_proxy v2.4.6
http.handlers.rewrite v2.4.6
http.handlers.static_response v2.4.6
http.handlers.subroute v2.4.6
http.handlers.templates v2.4.6
http.handlers.vars v2.4.6
http.matchers.expression v2.4.6
http.matchers.file v2.4.6
http.matchers.header v2.4.6
http.matchers.header_regexp v2.4.6
http.matchers.host v2.4.6
http.matchers.method v2.4.6
http.matchers.not v2.4.6
http.matchers.path v2.4.6
http.matchers.path_regexp v2.4.6
http.matchers.protocol v2.4.6
http.matchers.query v2.4.6
http.matchers.remote_ip v2.4.6
http.matchers.vars v2.4.6
http.matchers.vars_regexp v2.4.6
http.precompressed.br v2.4.6
http.precompressed.gzip v2.4.6
http.precompressed.zstd v2.4.6
http.reverse_proxy.selection_policies.cookie v2.4.6
http.reverse_proxy.selection_policies.first v2.4.6
http.reverse_proxy.selection_policies.header v2.4.6
http.reverse_proxy.selection_policies.ip_hash v2.4.6
http.reverse_proxy.selection_policies.least_conn v2.4.6
http.reverse_proxy.selection_policies.random v2.4.6
http.reverse_proxy.selection_policies.random_choose v2.4.6
http.reverse_proxy.selection_policies.round_robin v2.4.6
http.reverse_proxy.selection_policies.uri_hash v2.4.6
http.reverse_proxy.transport.fastcgi v2.4.6
http.reverse_proxy.transport.http v2.4.6
pki v2.4.6
tls v2.4.6
tls.certificates.automate v2.4.6
tls.certificates.load_files v2.4.6
tls.certificates.load_folders v2.4.6
tls.certificates.load_pem v2.4.6
tls.certificates.load_storage v2.4.6
tls.handshake_match.remote_ip v2.4.6
tls.handshake_match.sni v2.4.6
tls.issuance.acme v2.4.6
tls.issuance.internal v2.4.6
tls.issuance.zerossl v2.4.6
tls.stek.distributed v2.4.6
tls.stek.standard v2.4.6

  Standard modules: 83

dns.providers.googleclouddns v1.0.2
http.authentication.providers.authorizer v1.0.11
http.handlers.authenticator v1.0.11
http.handlers.trace v1.1.8
security v1.0.11

  Non-standard modules: 5

  Unknown modules: 0

Expected behavior

Presumably if I were to login I would see the UI list and the user information?

Additional context

I am using a VPS on Oracle Cloud Infrastructure and I am using Docker. I have a dockerfile and a docker compose file if necessary.

nginx style Forward Auth example.

Hello. caddyserver/caddy#2894 is closed citing this project's existence. Nginx' auth_request directive (https://nginx.org/en/docs/http/ngx_http_auth_request_module.html) works with a simple HTTP response code. Is this kind of functionality available? If yes, can you please direct me to the relevant documentation.

Another question while we're at it. It seems caddy-security is now a single module that includes the former authorize and portal components. Is it still possible to build it without the portal for people who already have an external authentication system in place?

feature: handling user authorization failed

A clear and concise description of what you want the system to do.

Currently, whether a user was previously authorized or whether the user wasn't authenticated, the user would get the same error:

2022/01/24 00:56:07.197 ERROR   http.handlers.authentication    auth provider returned error    {"provider": "authorizer", "error": "user authorization failed"}

There is a need to have different messages send to caddy.

breakfix: bypass URI not working

A clear and concise description of what you want to accomplish.

I want to bypass /api and some other paths from my policy

Before with caddy-auth I had this in my caddyfile; (worked fine)

qbit.website.com {
    import tls
    authorize {
        bypass uri prefix /api
        bypass uri prefix /command
        bypass uri prefix /query
        bypass uri prefix /login
        bypass uri prefix /sync
        set auth url https://auth.website.com
        allow roles authp/admin
		validate bearer header
		inject headers with claims
    }
    encode zstd gzip
    import headers	
    reverse_proxy qbittorrent:8080
}

Now with caddy-security Im trying to achieve the same thing, so I looked here:
https://authp.github.io/docs/authorize/bypass

    security {
		authentication portal myportal {
	     crypto default token lifetime 86400
             cookie lifetime 172800
             cookie domain website.com
			 backend local /config/auth/local/users2.json local
             ui {
                 links {
                      "Flame" https://flame.website.com/ icon "las la-star"
                 }
             }
			 transform user {
                match email [email protected]
				action add role authp/admin	
			}
        }
		authorization policy admins_policy {
            bypass uri prefix /api
            bypass uri prefix /command
            bypass uri prefix /query
            bypass uri prefix /login
            bypass uri prefix /sync
            allow roles authp/admin
            set auth url https://auth.website.com/
			acl rule {
				comment default deny
				match any
				deny log warn
			}
		}
    }

This however does not work, the reverse proxy stops working after auth is done (shows a blank page), also log spams with:

{"level":"error","ts":1643842456.2998343,"logger":"http.handlers.authentication","msg":"auth provider returned error","provider":"authorizer","error":"user authorization failed: src_ip=IP, src_conn_ip=IP, reason: user data not found"}

{"level":"error","ts":1643842194.8351867,"logger":"http.handlers.authentication","msg":"auth provider returned error","provider":"authorizer","error":"user authorization failed: src_ip=IP, src_conn_ip=IP, reason: no token found"}

Am I not understanding the bypass function? Or is it a better way to do this? Thanks

`auth provider returned error, user authorization failed` being spammed in Caddy log

Describe the issue
I'm trying to migrate my config over to Caddy Security, and I think I have most things working now, but I'm getting this message constantly spammed in Caddy's log:

{"level":"error","ts":1642791051.2186432,"logger":"http.handlers.authentication","msg":"auth provider returned error","provider":"authorizer","error":"user authorization failed"}

The interesting thing is, it doesn't seem to affect the functionality, because I'm able to login just fine.

Configuration

{ # Global configuration
    acme_dns cloudflare REDACTED
    email REDACTED
    order authorize before reverse_proxy
    order authenticate before authorize
    security {
        credentials email smtp.sendgrid.net {
            address smtp.sendgrid.net:587
            protocol smtp
            username {env.SMTP_USERNAME}
            password {env.SMTP_PASSWORD}
        }
        authentication portal myportal {
            crypto default token lifetime 3600
            # crypto key sign-verify {env.JWT_SECRET}
            backend local /etc/caddy/auth/local/users.json local
                    cookie domain haddock.cc
            ui {
                links { # Icons here -> https://icons8.com/line-awesome
                    "Cloud" https://cloud.haddock.cc icon "las la-cloud"
                    "Media" https://media.haddock.cc icon "las la-photo-video"
                    "Get TV Shows" https://tv.haddock.cc icon "las la-tv"
                    "Get Movies" https://movies.haddock.cc icon "las la-video"
                }
            }
            transform user {
                match origin local
                action add role authp/user
                ui link "Portal Settings" /settings icon "las la-cog"
            }
        }
        authorization policy mypolicy {
            set auth url https://auth.haddock.cc/
            allow roles authp/admin authp/user
        }
    }
    # }
    # crowdsec {
    #     api_url http://crowdsec:8180/
    #     api_key REDACTED
    #     ticker_interval 15s
    # }
}

auth.haddock.cc {
    authenticate * with myportal
}

cloud.haddock.cc {
    authorize with mypolicy
        reverse_proxy nextcloud:80 {
        header_down Strict-Transport-Security "max-age=15552000; includeSubDomains"
    }
    rewrite /.well-known/carddav /remote.php/dav
    rewrite /.well-known/caldav /remote.php/dav
}

media.haddock.cc {
    authorize with mypolicy
    reverse_proxy jellyfin:8096
}

indexers.haddock.cc { # Prowlarr
    authorize with mypolicy
    reverse_proxy prowlarr:9696
}

tv.haddock.cc { # Sonarr
    authorize with mypolicy
    reverse_proxy sonarr:8989
}

movies.haddock.cc { # Radarr
    authorize with mypolicy
    reverse_proxy radarr:7878
}

localhost:8112 { # QBittorrent
    reverse_proxy torrent:8080
}

Version Information

crowdsec v0.2.0
dns.providers.cloudflare v0.0.0-20210607183747-91cf700356a1
http.authentication.providers.authorizer v1.0.1
http.handlers.authenticator v1.0.1
http.handlers.crowdsec v0.2.0
layer4 v0.0.0-20201230212151-6587f40d4eb6
layer4.matchers.crowdsec v0.2.0
layer4.matchers.ip v0.0.0-20201230212151-6587f40d4eb6
security v1.0.1

Expected behavior
The Caddy log isn't filled up with the error.

question: accessing portal over non-HTTPS port.

Describe the issue

I cannot login into a webadmin account when accessing Caddy server thought other IP than localhost.

Caddy debug message shows: sandbox secret not found

Configuration

{
	http_port 8080
	debug

	order authenticate before respond
	order authorize before basicauth
	security {
		authentication portal myportal {
			backend local {env.HOME}/.local/caddy/users.json local
		}
	}
}

:8080 {
	route {
		authenticate with myportal
	}
	file_server browse
}

Version Information

admin.api.load v2.4.6
admin.api.metrics v2.4.6
admin.api.reverse_proxy v2.4.6
caddy.adapters.caddyfile v2.4.6
caddy.config_loaders.http v2.4.6
caddy.listeners.tls v2.4.6
caddy.logging.encoders.console v2.4.6
caddy.logging.encoders.filter v2.4.6
caddy.logging.encoders.filter.delete v2.4.6
caddy.logging.encoders.filter.ip_mask v2.4.6
caddy.logging.encoders.filter.replace v2.4.6
caddy.logging.encoders.json v2.4.6
caddy.logging.encoders.single_field v2.4.6
caddy.logging.writers.discard v2.4.6
caddy.logging.writers.file v2.4.6
caddy.logging.writers.net v2.4.6
caddy.logging.writers.stderr v2.4.6
caddy.logging.writers.stdout v2.4.6
caddy.storage.file_system v2.4.6
http v2.4.6
http.authentication.hashes.bcrypt v2.4.6
http.authentication.hashes.scrypt v2.4.6
http.authentication.providers.http_basic v2.4.6
http.encoders.gzip v2.4.6
http.encoders.zstd v2.4.6
http.handlers.acme_server v2.4.6
http.handlers.authentication v2.4.6
http.handlers.encode v2.4.6
http.handlers.error v2.4.6
http.handlers.file_server v2.4.6
http.handlers.headers v2.4.6
http.handlers.map v2.4.6
http.handlers.metrics v2.4.6
http.handlers.push v2.4.6
http.handlers.request_body v2.4.6
http.handlers.reverse_proxy v2.4.6
http.handlers.rewrite v2.4.6
http.handlers.static_response v2.4.6
http.handlers.subroute v2.4.6
http.handlers.templates v2.4.6
http.handlers.vars v2.4.6
http.matchers.expression v2.4.6
http.matchers.file v2.4.6
http.matchers.header v2.4.6
http.matchers.header_regexp v2.4.6
http.matchers.host v2.4.6
http.matchers.method v2.4.6
http.matchers.not v2.4.6
http.matchers.path v2.4.6
http.matchers.path_regexp v2.4.6
http.matchers.protocol v2.4.6
http.matchers.query v2.4.6
http.matchers.remote_ip v2.4.6
http.matchers.vars v2.4.6
http.matchers.vars_regexp v2.4.6
http.precompressed.br v2.4.6
http.precompressed.gzip v2.4.6
http.precompressed.zstd v2.4.6
http.reverse_proxy.selection_policies.cookie v2.4.6
http.reverse_proxy.selection_policies.first v2.4.6
http.reverse_proxy.selection_policies.header v2.4.6
http.reverse_proxy.selection_policies.ip_hash v2.4.6
http.reverse_proxy.selection_policies.least_conn v2.4.6
http.reverse_proxy.selection_policies.random v2.4.6
http.reverse_proxy.selection_policies.random_choose v2.4.6
http.reverse_proxy.selection_policies.round_robin v2.4.6
http.reverse_proxy.selection_policies.uri_hash v2.4.6
http.reverse_proxy.transport.fastcgi v2.4.6
http.reverse_proxy.transport.http v2.4.6
pki v2.4.6
tls v2.4.6
tls.certificates.automate v2.4.6
tls.certificates.load_files v2.4.6
tls.certificates.load_folders v2.4.6
tls.certificates.load_pem v2.4.6
tls.certificates.load_storage v2.4.6
tls.handshake_match.remote_ip v2.4.6
tls.handshake_match.sni v2.4.6
tls.issuance.acme v2.4.6
tls.issuance.internal v2.4.6
tls.issuance.zerossl v2.4.6
tls.stek.distributed v2.4.6
tls.stek.standard v2.4.6

  Standard modules: 83

http.authentication.providers.authorizer v1.0.12
http.handlers.authenticator v1.0.12
security v1.0.12

  Non-standard modules: 3

  Unknown modules: 0

Expected behavior

Ability to authenticate when accessing Caddyserver via IP,hostname other than localhost.

Additional context

Caddy server accessed via 192.168.0.171:8080 returns

2022/02/03 20:19:24.033 DEBUG   security        static assets   {"session_id": "WNe9Erc4sxpt5Lq7zklXLsMlKzLuw54PMFDj", "request_id": "e470bcf6-55d9-44a5-b758-7a258bbef2c5", "url_path": "/assets/google-webfonts/fonts/roboto-v20-latin-500.woff2", "request": {"session_id":"WNe9Erc4sxpt5Lq7zklXLsMlKzLuw54PMFDj","base_url":"http://192.168.0.171:8080","base_path":"/","content_type":"application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"}, "source_address": "192.168.0.171"}
2022/02/03 20:19:26.793 DEBUG   security        failed sandbox request  {"session_id": "Scgx1FyAkGsRtn9XOJFmPAW0nrq46xGed57zMD", "request_id": "2cfc7032-717b-40d3-a275-de3208ba1f7a", "error": "sandbox secret not found"}

However when I access the very same instance of Caddy server by putting 'localhost:8080' in a web-browser I am correctly redirected to a Password Authentication page. Everything works as expected:

2022/02/03 20:25:02.630 DEBUG   security        Redirect served {"session_id": "aNJELgcNiwDugTEU69VAH8LuzrUDhNQnY3fs2j", "request_id": "0f15333e-1ef4-4eda-b404-2c9bdac66104", "redirect_url": "http://localhost:8080/login", "status_code": 302}
2022/02/03 20:25:02.706 DEBUG   security        static assets   {"session_id": "aNJELgcNiwDugTEU69VAH8LuzrUDhNQnY3fs2j", "request_id": "6edb562a-47bd-439b-a0ad-b392bbc02b71", "url_path": "/assets/google-webfonts/fonts/roboto-v20-latin-regular.woff2", "request": {"session_id":"aNJELgcNiwDugTEU69VAH8LuzrUDhNQnY3fs2j","base_url":"http://localhost:8080","base_path":"/","content_type":"application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"}, "source_address": "127.0.0.1"}
2022/02/03 20:25:05.931 DEBUG   security        user authorization sandbox      {"sandbox_id": "91rn1fpYbCHrVuwfRrky99yZfK8Om2swG9IEkksXT1FE", "sandbox_secret": "KDsCVc5apZTfRCem6XfG9nF5w4iTpIaBcCfoGgrVR6H", "sandbox_partition": "", "checkpoints": [{"name":"Authenticate with password","type":"password"}]}
2022/02/03 20:25:05.931 DEBUG   security        next user authorization checkpoint      {"session_id": "aNJELgcNiwDugTEU69VAH8LuzrUDhNQnY3fs2j", "request_id": "aa7c54c5-b8f9-47af-9e8c-63ea12cf7363", "data": {"action":"auth","title":"Password Authentication","view":"password_auth"}}

feature: push notification security challenge for Microsoft Authenticator

A clear and concise description of what you want the system to do.

Implement security challenge of type push.

A user provides a username/email at the login screen. Then, the user is redirected to sandbox. In the sandbox, the user land on "Push Notification" page. That would trigger Approve/Decline screen on the user's phone screen. The page would continue polling the sandbox endpoint for the status of the push notification.

The transform that would trigger the push notification is:

transform user {
  match ...
  require push with msauth
}

Then, the configuration for MS Authenticator might look something like:

push provider msauth {
  ... config
}

feature: add user management page

A clear and concise description of what you want the system to do.

Add "User Management" page where users with the role "authp/admin" can manager users and approve registrations.

Current status

Angular app is under development. I built the initial skeleton for the app.

Next step: Adding approval page.

How to get it?

Please email me ([email protected]) with the subject "Auth Portal UI Access" expressing interest in the UI. I will send instructions on how to get it started and test it.

The app is not open-source yet.

Who gets it:

  • My sponsors
  • Anyone under 21
  • Students and Educators
  • Anyone who does not have money to sponsor me

breakfix: Custom css path seems not working

Custom css path does not work

Today I updated from caddy-auth-portal to caddy-security. Everything is fine except for custom css path directive.
I haven't changed it this time in any way and followed the documentation.
In the developer console /auth/assets/css/custom.css returns 404
No errors in caddy's log.

Configuration

{
        security {
                authentication portal badass_security {
                        cookie domain domain.dev
                        crypto default token lifetime 865000
                        cookie lifetime 865000
                        backend local /auth/users.json local
                        ui {
                                custom css path /auth/auth_style.css
                                template sandbox /auth/template/sandbox.template
                                template login /auth/template/login.template
                        }
                }
                authorization policy badass_policy {
                        set auth url https://domain.dev/auth
                        allow roles authp/admin
                }
        }
}

domain.dev {
        @auth {
                path /*
                not {
                        path /robots.txt
                        path /favicon.ico
                        path /no_auth*
                }
        }
        root * /srv
        file_server
        route @auth {
                authorize with badass_policy
        }
        route /auth* {
        	    authenticate with badass_security
        }
}

subdomain.domain.dev {
        route {
                authorize with badass_policy
        }
        reverse_proxy 127.0.0.1:3009
}

Version Information

/etc/caddy # caddy list-modules -versions
admin.api.load v2.4.6
admin.api.metrics v2.4.6
admin.api.reverse_proxy v2.4.6
caddy.adapters.caddyfile v2.4.6
caddy.config_loaders.http v2.4.6
caddy.listeners.tls v2.4.6
caddy.logging.encoders.console v2.4.6
caddy.logging.encoders.filter v2.4.6
caddy.logging.encoders.filter.delete v2.4.6
caddy.logging.encoders.filter.ip_mask v2.4.6
caddy.logging.encoders.filter.replace v2.4.6
caddy.logging.encoders.json v2.4.6
caddy.logging.encoders.single_field v2.4.6
caddy.logging.writers.discard v2.4.6
caddy.logging.writers.file v2.4.6
caddy.logging.writers.net v2.4.6
caddy.logging.writers.stderr v2.4.6
caddy.logging.writers.stdout v2.4.6
caddy.storage.file_system v2.4.6
http v2.4.6
http.authentication.hashes.bcrypt v2.4.6
http.authentication.hashes.scrypt v2.4.6
http.authentication.providers.http_basic v2.4.6
http.encoders.gzip v2.4.6
http.encoders.zstd v2.4.6
http.handlers.acme_server v2.4.6
http.handlers.authentication v2.4.6
http.handlers.encode v2.4.6
http.handlers.error v2.4.6
http.handlers.file_server v2.4.6
http.handlers.headers v2.4.6
http.handlers.map v2.4.6
http.handlers.metrics v2.4.6
http.handlers.push v2.4.6
http.handlers.request_body v2.4.6
http.handlers.reverse_proxy v2.4.6
http.handlers.rewrite v2.4.6
http.handlers.static_response v2.4.6
http.handlers.subroute v2.4.6
http.handlers.templates v2.4.6
http.handlers.vars v2.4.6
http.matchers.expression v2.4.6
http.matchers.file v2.4.6
http.matchers.header v2.4.6
http.matchers.header_regexp v2.4.6
http.matchers.host v2.4.6
http.matchers.method v2.4.6
http.matchers.not v2.4.6
http.matchers.path v2.4.6
http.matchers.path_regexp v2.4.6
http.matchers.protocol v2.4.6
http.matchers.query v2.4.6
http.matchers.remote_ip v2.4.6
http.matchers.vars v2.4.6
http.matchers.vars_regexp v2.4.6
http.precompressed.br v2.4.6
http.precompressed.gzip v2.4.6
http.precompressed.zstd v2.4.6
http.reverse_proxy.selection_policies.cookie v2.4.6
http.reverse_proxy.selection_policies.first v2.4.6
http.reverse_proxy.selection_policies.header v2.4.6
http.reverse_proxy.selection_policies.ip_hash v2.4.6
http.reverse_proxy.selection_policies.least_conn v2.4.6
http.reverse_proxy.selection_policies.random v2.4.6
http.reverse_proxy.selection_policies.random_choose v2.4.6
http.reverse_proxy.selection_policies.round_robin v2.4.6
http.reverse_proxy.selection_policies.uri_hash v2.4.6
http.reverse_proxy.transport.fastcgi v2.4.6
http.reverse_proxy.transport.http v2.4.6
pki v2.4.6
tls v2.4.6
tls.certificates.automate v2.4.6
tls.certificates.load_files v2.4.6
tls.certificates.load_folders v2.4.6
tls.certificates.load_pem v2.4.6
tls.certificates.load_storage v2.4.6
tls.handshake_match.remote_ip v2.4.6
tls.handshake_match.sni v2.4.6
tls.issuance.acme v2.4.6
tls.issuance.internal v2.4.6
tls.issuance.zerossl v2.4.6
tls.stek.distributed v2.4.6
tls.stek.standard v2.4.6

  Standard modules: 83

http.authentication.providers.authorizer v1.0.6
http.handlers.authenticator v1.0.6
security v1.0.6

  Non-standard modules: 3

  Unknown modules: 0

Expected behavior

Custom css should work

Additional context

Custom templates DO work fine.

The file exists and in previous version it works fine.

Here is the previous authp directive:

route /auth* {
                authp {
                        cookie domain domain.dev
                        crypto default token lifetime 865000
                        cookie lifetime 865000
                        backends {
                                local_backend {
                                        method local
                                        path /auth/users.json
                                        realm local
                                }
                        }
                        ui {
                                custom css path /auth/auth_style.css
                                template sandbox /auth/template/sandbox.template
                                template login /auth/template/login.template
                        }
                }
        }

feature: Internationalization (i18n)

A clear and concise description of what you want the system to do.

List of "translatable" works:

  • ./pkg/authn/handle_http_sandbox.go: Password authentication failed. Please retry

feature: shared secrets store

Add credentials store so that it can be accessible by auth portal and authorize plugin subsystems.

For example, I want to store AWS credentials and being able to access it from various Caddy plugins.

Create the code necessary to support this in pkg/shared/secrets directory. It should be similar to the code in pkg/shared/idp.

Original issue: https://github.com/greenpau/caddy-authorize/issues/97

consul backend as user data store

A clear and concise description of what you want the system to do.

An idea has come to me.

The local user.json is nice and simple for smaller projects but doesn't quite meet the requirements

I've been thinking about a Hashiport Consul backend or even a Hashicorp Vault backend (which itself can use Consul as a backend) to store user data.

This would allow to benefit from Consul's HA and would make it easier to deploy Caddy Auth servers when we don't have to deal with volumes for local storage.

I wondered, how you think about it. As an inspiration, there is already a storage plugin for consul https://github.com/pteich/caddy-tlsconsul

What are the Caddyfile directives that need to be added.

Add Caddyfile directive:

{
  security {
    authentication portal myportal {
      registration {
         consul {
           address  "127.0.0.1:8500"
           token  "consul-access-token"
           timeout  10
           prefix  "myportal"
           value_prefix "portal_users"
           aes_key "consultls-1234567890-caddytls-32"
           tls_enabled  "false"
           tls_insecure "true"
        }
        title "User Registration"
        code "NY2020"
        require accept terms
        require domain mx
        admin email [email protected] [email protected]
      }
    }
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.