loading...
;
37 | }
38 |
39 | const rows = this.devices.current;
40 |
41 | // show the provider column
42 | // when there is more than 1 provider in use
43 | // i.e. not all devices are from the same auth provider.
44 | const showProviderCol = rows.length >= 2 && rows.some((r) => r.ownerProvider !== rows[0].ownerProvider);
45 |
46 | return (
47 |
48 |
49 | Devices
50 |
51 |
52 |
53 |
54 |
55 | Owner
56 | {showProviderCol && Auth Provider }
57 | Device
58 | Connected
59 | Last Seen
60 | Actions
61 |
62 |
63 |
64 | {rows.map((row, i) => (
65 |
66 |
67 | {row.ownerName || row.ownerEmail || row.owner}
68 |
69 | {showProviderCol && {row.ownerProvider} }
70 | {row.name}
71 | {row.connected ? 'yes' : 'no'}
72 | {lastSeen(row.lastHandshakeTime)}
73 |
74 | this.deleteDevice(row)}>
75 | Delete
76 |
77 |
78 |
79 | ))}
80 |
81 |
82 |
83 |
84 | Server Info
85 |
86 |
87 |
88 | {JSON.stringify(AppState.info, null, 2)}
89 |
90 |
91 |
92 |
93 | );
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/pkg/authnz/router.go:
--------------------------------------------------------------------------------
1 | package authnz
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "strconv"
7 |
8 | "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
9 | "github.com/pkg/errors"
10 |
11 | "github.com/place1/wg-access-server/pkg/authnz/authconfig"
12 | "github.com/place1/wg-access-server/pkg/authnz/authruntime"
13 | "github.com/place1/wg-access-server/pkg/authnz/authsession"
14 | "github.com/place1/wg-access-server/pkg/authnz/authtemplates"
15 | "github.com/place1/wg-access-server/pkg/authnz/authutil"
16 |
17 | "github.com/gorilla/mux"
18 | "github.com/gorilla/sessions"
19 | )
20 |
21 | type AuthMiddleware struct {
22 | config authconfig.AuthConfig
23 | claimsMiddleware authsession.ClaimsMiddleware
24 | router *mux.Router
25 | runtime *authruntime.ProviderRuntime
26 | }
27 |
28 | func New(config authconfig.AuthConfig, claimsMiddleware authsession.ClaimsMiddleware) *AuthMiddleware {
29 | router := mux.NewRouter()
30 | store := sessions.NewCookieStore([]byte(authutil.RandomString(32)))
31 | runtime := authruntime.NewProviderRuntime(store)
32 | providers := config.Providers()
33 |
34 | for _, p := range providers {
35 | if p.RegisterRoutes != nil {
36 | p.RegisterRoutes(router, runtime)
37 | }
38 | }
39 |
40 | router.HandleFunc("/signin", func(w http.ResponseWriter, r *http.Request) {
41 | w.WriteHeader(http.StatusOK)
42 | fmt.Fprint(w, authtemplates.RenderLoginPage(w, authtemplates.LoginPage{
43 | Providers: providers,
44 | }))
45 | })
46 |
47 | router.HandleFunc("/signin/{index}", func(w http.ResponseWriter, r *http.Request) {
48 | index, err := strconv.Atoi(mux.Vars(r)["index"])
49 | if err != nil || index < 0 || len(providers) <= index {
50 | w.WriteHeader(http.StatusBadRequest)
51 | fmt.Fprintf(w, "unknown provider")
52 | return
53 | }
54 | provider := providers[index]
55 | provider.Invoke(w, r, runtime)
56 | })
57 |
58 | router.HandleFunc("/signout", func(w http.ResponseWriter, r *http.Request) {
59 | runtime.ClearSession(w, r)
60 | runtime.Restart(w, r)
61 | })
62 |
63 | return &AuthMiddleware{
64 | config,
65 | claimsMiddleware,
66 | router,
67 | runtime,
68 | }
69 | }
70 |
71 | func NewMiddleware(config authconfig.AuthConfig, claimsMiddleware authsession.ClaimsMiddleware) mux.MiddlewareFunc {
72 | return New(config, claimsMiddleware).Middleware
73 | }
74 |
75 | func (m *AuthMiddleware) Middleware(next http.Handler) http.Handler {
76 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
77 | // check if the request is for an auth
78 | // related page i.e. /signin
79 | // to be handled by our own router
80 | if ok := m.router.Match(r, &mux.RouteMatch{}); ok {
81 | m.router.ServeHTTP(w, r)
82 | return
83 | }
84 |
85 | // otherwise we apply the standard middleware
86 | // functionality i.e. annotate the request context
87 | // with the request user (identity)
88 | if s, err := m.runtime.GetSession(r); err == nil {
89 | if m.claimsMiddleware != nil {
90 | if err := m.claimsMiddleware(s.Identity); err != nil {
91 | ctxlogrus.Extract(r.Context()).Error(errors.Wrap(err, "authz middleware failure"))
92 | http.Error(w, "internal server error", http.StatusInternalServerError)
93 | return
94 | }
95 | }
96 | next.ServeHTTP(w, r.WithContext(authsession.SetIdentityCtx(r.Context(), s)))
97 | } else {
98 | next.ServeHTTP(w, r)
99 | }
100 | })
101 | }
102 |
103 | func RequireAuthentication(next http.Handler) http.Handler {
104 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
105 | if authsession.Authenticated(r.Context()) {
106 | next.ServeHTTP(w, r)
107 | } else {
108 | http.Redirect(w, r, "/signin", http.StatusTemporaryRedirect)
109 | }
110 | })
111 | }
112 |
--------------------------------------------------------------------------------
/docs/4-auth.md:
--------------------------------------------------------------------------------
1 | # Authentication
2 |
3 | Authentication is pluggable in wg-access-server. Community contributions are welcome
4 | for supporting new authentication backends.
5 |
6 | If you're just getting started you can skip over this section and rely on the default
7 | admin account instead.
8 |
9 | If your authentication system is not yet supported and you aren't quite ready to
10 | contribute you could try using a project like [dex](https://github.com/dexidp/dex)
11 | or SaaS provider like [Auth0](https://auth0.com/) which supports a wider variety of
12 | authentication protocols. wg-access-server can happily be an OpenID Connect client
13 | to a larger solution like this.
14 |
15 | The following authentication backends are currently supported:
16 |
17 | | Backend | Use Case | Notes |
18 | | -------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
19 | | Basic Auth | Deployments with a static list of users. Simple and great for self-hosters and home use-cases | The wg-access-server admin account is powered by this backend |
20 | | OpenID Connect | For delegating authentication to an existing identity solution | |
21 | | Gitlab | For delegating authentication to gitlab. Supports self-hosted Gitlab. | |
22 |
23 | ## Configuration
24 |
25 | Currently authentication providers are only configurable via the wg-access-server
26 | config file (config.yaml).
27 |
28 | Below is an annotated example config section that can be used as a starting point.
29 |
30 | ```yaml
31 | # Configure zero or more authentication backends
32 | auth:
33 | # HTTP Basic Authentication
34 | basic:
35 | # Users is a list of htpasswd encoded username:password pairs
36 | # supports BCrypt, Sha, Ssha, Md5
37 | # You can create a user using "htpasswd -nB