-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(example): Allow configuring some parameters with env variables (#…
…663) Co-authored-by: Andrey Rusakov <[email protected]>
- Loading branch information
Showing
6 changed files
with
262 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ Whenever possible we tried to reuse / extend existing packages like `OAuth2 for | |
The most important packages of the library: | ||
<pre> | ||
/pkg | ||
/client clients using the OP for retrieving, exchanging and verifying tokens | ||
/client clients using the OP for retrieving, exchanging and verifying tokens | ||
/rp definition and implementation of an OIDC Relying Party (client) | ||
/rs definition and implementation of an OAuth Resource Server (API) | ||
/op definition and implementation of an OIDC OpenID Provider (server) | ||
|
@@ -55,21 +55,51 @@ CLIENT_ID=web CLIENT_SECRET=secret ISSUER=http://localhost:9998/ SCOPES="openid | |
``` | ||
|
||
- open http://localhost:9999/login in your browser | ||
- you will be redirected to op server and the login UI | ||
- you will be redirected to op server and the login UI | ||
- login with user `test-user@localhost` and password `verysecure` | ||
- the OP will redirect you to the client app, which displays the user info | ||
|
||
for the dynamic issuer, just start it with: | ||
```bash | ||
go run github.com/zitadel/oidc/v3/example/server/dynamic | ||
``` | ||
``` | ||
the oidc web client above will still work, but if you add `oidc.local` (pointing to 127.0.0.1) in your hosts file you can also start it with: | ||
```bash | ||
CLIENT_ID=web CLIENT_SECRET=secret ISSUER=http://oidc.local:9998/ SCOPES="openid profile" PORT=9999 go run github.com/zitadel/oidc/v3/example/client/app | ||
``` | ||
|
||
> Note: Usernames are suffixed with the hostname (`test-user@localhost` or `[email protected]`) | ||
### Server configuration | ||
|
||
Example server allows extra configuration using environment variables and could be used for end to | ||
end testing of your services. | ||
|
||
| Name | Format | Description | | ||
|---------------|--------------------------------------|---------------------------------------| | ||
| PORT | Number between 1 and 65535 | OIDC listen port | | ||
| REDIRECT_URI | Comma-separated URIs | List of allowed redirect URIs | | ||
| USERS_FILE | Path to json in local filesystem | Users with their data and credentials | | ||
|
||
Here is json equivalent for one of the default users | ||
```json | ||
{ | ||
"id2": { | ||
"ID": "id2", | ||
"Username": "test-user2", | ||
"Password": "verysecure", | ||
"FirstName": "Test", | ||
"LastName": "User2", | ||
"Email": "[email protected]", | ||
"EmailVerified": true, | ||
"Phone": "", | ||
"PhoneVerified": false, | ||
"PreferredLanguage": "DE", | ||
"IsAdmin": false | ||
} | ||
} | ||
``` | ||
|
||
## Features | ||
|
||
| | Relying party | OpenID Provider | Specification | | ||
|
@@ -115,7 +145,7 @@ For your convenience you can find the relevant guides linked below. | |
|
||
## Supported Go Versions | ||
|
||
For security reasons, we only support and recommend the use of one of the latest two Go versions (:white_check_mark:). | ||
For security reasons, we only support and recommend the use of one of the latest two Go versions (:white_check_mark:). | ||
Versions that also build are marked with :warning:. | ||
|
||
| Version | Supported | | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package config | ||
|
||
import ( | ||
"os" | ||
"strings" | ||
) | ||
|
||
const ( | ||
// default port for the http server to run | ||
DefaultIssuerPort = "9998" | ||
) | ||
|
||
type Config struct { | ||
Port string | ||
RedirectURI []string | ||
UsersFile string | ||
} | ||
|
||
// FromEnvVars loads configuration parameters from environment variables. | ||
// If there is no such variable defined, then use default values. | ||
func FromEnvVars(defaults *Config) *Config { | ||
if defaults == nil { | ||
defaults = &Config{} | ||
} | ||
cfg := &Config{ | ||
Port: defaults.Port, | ||
RedirectURI: defaults.RedirectURI, | ||
UsersFile: defaults.UsersFile, | ||
} | ||
if value, ok := os.LookupEnv("PORT"); ok { | ||
cfg.Port = value | ||
} | ||
if value, ok := os.LookupEnv("USERS_FILE"); ok { | ||
cfg.UsersFile = value | ||
} | ||
if value, ok := os.LookupEnv("REDIRECT_URI"); ok { | ||
cfg.RedirectURI = strings.Split(value, ",") | ||
} | ||
return cfg | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package config | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"testing" | ||
) | ||
|
||
func TestFromEnvVars(t *testing.T) { | ||
|
||
for _, tc := range []struct { | ||
name string | ||
env map[string]string | ||
defaults *Config | ||
want *Config | ||
}{ | ||
{ | ||
name: "no vars, no default values", | ||
env: map[string]string{}, | ||
want: &Config{}, | ||
}, | ||
{ | ||
name: "no vars, only defaults", | ||
env: map[string]string{}, | ||
defaults: &Config{ | ||
Port: "6666", | ||
UsersFile: "/default/user/path", | ||
RedirectURI: []string{"re", "direct", "uris"}, | ||
}, | ||
want: &Config{ | ||
Port: "6666", | ||
UsersFile: "/default/user/path", | ||
RedirectURI: []string{"re", "direct", "uris"}, | ||
}, | ||
}, | ||
{ | ||
name: "overriding default values", | ||
env: map[string]string{ | ||
"PORT": "1234", | ||
"USERS_FILE": "/path/to/users", | ||
"REDIRECT_URI": "http://redirect/redirect", | ||
}, | ||
defaults: &Config{ | ||
Port: "6666", | ||
UsersFile: "/default/user/path", | ||
RedirectURI: []string{"re", "direct", "uris"}, | ||
}, | ||
want: &Config{ | ||
Port: "1234", | ||
UsersFile: "/path/to/users", | ||
RedirectURI: []string{"http://redirect/redirect"}, | ||
}, | ||
}, | ||
{ | ||
name: "multiple redirect uris", | ||
env: map[string]string{ | ||
"REDIRECT_URI": "http://host_1,http://host_2,http://host_3", | ||
}, | ||
want: &Config{ | ||
RedirectURI: []string{ | ||
"http://host_1", "http://host_2", "http://host_3", | ||
}, | ||
}, | ||
}, | ||
} { | ||
t.Run(tc.name, func(t *testing.T) { | ||
os.Clearenv() | ||
for k, v := range tc.env { | ||
os.Setenv(k, v) | ||
} | ||
cfg := FromEnvVars(tc.defaults) | ||
if fmt.Sprint(cfg) != fmt.Sprint(tc.want) { | ||
t.Errorf("Expected FromEnvVars()=%q, but got %q", tc.want, cfg) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package storage | ||
|
||
import ( | ||
"os" | ||
"path" | ||
"reflect" | ||
"testing" | ||
|
||
"golang.org/x/text/language" | ||
) | ||
|
||
func TestStoreFromFile(t *testing.T) { | ||
for _, tc := range []struct { | ||
name string | ||
pathToFile string | ||
content string | ||
want UserStore | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "normal user file", | ||
pathToFile: "userfile.json", | ||
content: `{ | ||
"id1": { | ||
"ID": "id1", | ||
"EmailVerified": true, | ||
"PreferredLanguage": "DE" | ||
} | ||
}`, | ||
want: userStore{map[string]*User{ | ||
"id1": { | ||
ID: "id1", | ||
EmailVerified: true, | ||
PreferredLanguage: language.German, | ||
}, | ||
}}, | ||
}, | ||
{ | ||
name: "malformed file", | ||
pathToFile: "whatever", | ||
content: "not a json just a text", | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "not existing file", | ||
pathToFile: "what/ever/file", | ||
wantErr: true, | ||
}, | ||
} { | ||
t.Run(tc.name, func(t *testing.T) { | ||
actualPath := path.Join(t.TempDir(), tc.pathToFile) | ||
|
||
if tc.content != "" && tc.pathToFile != "" { | ||
if err := os.WriteFile(actualPath, []byte(tc.content), 0666); err != nil { | ||
t.Fatalf("cannot create file with test content: %q", tc.content) | ||
} | ||
} | ||
result, err := StoreFromFile(actualPath) | ||
if err != nil && !tc.wantErr { | ||
t.Errorf("StoreFromFile(%q) returned unexpected error %q", tc.pathToFile, err) | ||
} else if err == nil && tc.wantErr { | ||
t.Errorf("StoreFromFile(%q) did not return an expected error", tc.pathToFile) | ||
} | ||
if !tc.wantErr && !reflect.DeepEqual(tc.want, result.(userStore)) { | ||
t.Errorf("expected StoreFromFile(%q) = %v, but got %v", | ||
tc.pathToFile, tc.want, result) | ||
} | ||
}) | ||
} | ||
} |