Skip to content

Commit

Permalink
chore: support Auth0 client playing nicely with other OAuth2/OIDC pro…
Browse files Browse the repository at this point in the history
…viders

Omni doesn't use a generic OAuth2/OIDC client/SDK instead it uses the Auth0 SDK for Vue and it's using a pretty old version,  v1.0.2 as can be seen by inspecting the Omni package.json [here](https://github.com/siderolabs/omni/blob/7fb5d2b20a9372e1a0906b9384696daf93a45c51/frontend/package.json#L13). This SDK in turn uses [auth0-spa-js](https://github.com/auth0/auth0-spa-js) v1.22.1 which can be seen by inspecting its package.json [here](https://github.com/auth0/auth0-vue/blob/bb3bc817d18b8b6d68f3292fe6fadb31f28320db/package.json#L80).

**This has significant implications as the v1 of the SDK is not compliant with OAuth2 in 1 critical area.**

OAuth2 mandates the use of  the `application/x-www-form-urlencoded` content type for grant messages sent to the token endpoint and that sending JSON request bodies will result in a 400 error.

Unfortunately the v1 of the SDK sends the request payload as JSON which means that IdPs such as Authentik rightfully returns a 400 error and this results in an infinite loop of requests from Omni to Authentik.

The behavior can be confirmed by looking at the comment in the Auth0 SDK code [here](https://github.com/auth0/auth0-spa-js/blob/371e5a82a6da3be24a2f89b7a3a4473f01156c02/src/global.ts#L251). Interestingly the default for the `useFormData` was changed to `true` in v1.22.6 of the SDK.

This PR introduces a new Omni flag called `--auth-auth0-use-form-data`. By default the flag is set to `false` to maintain backwards compatibility. If the flag is set to `true` then the Auth0 client is created with the `useFormData` set to `true`

Signed-off-by: Sherif Fanous <[email protected]>
Signed-off-by: Artem Chernyshev <[email protected]>
  • Loading branch information
Sherif Fanous authored and Unix4ever committed Apr 12, 2024
1 parent de4c096 commit 2e015a9
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 178 deletions.
346 changes: 178 additions & 168 deletions client/api/omni/specs/auth.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client/api/omni/specs/auth.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ message AuthConfigSpec {
bool enabled = 1;
string domain = 2;
string client_id = 3;
bool useFormData = 4;
}

message Webauthn {
Expand Down
37 changes: 37 additions & 0 deletions client/api/omni/specs/auth_vtproto.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cmd/omni/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ func init() {
"enable Auth0 authentication. Once set to true, it cannot be set back to false.")
rootCmd.Flags().StringVar(&config.Config.Auth.Auth0.ClientID, "auth-auth0-client-id", config.Config.Auth.Auth0.ClientID, "Auth0 application client ID.")
rootCmd.Flags().StringVar(&config.Config.Auth.Auth0.Domain, "auth-auth0-domain", config.Config.Auth.Auth0.Domain, "Auth0 application domain.")
rootCmd.Flags().BoolVar(&config.Config.Auth.Auth0.UseFormData, "auth-auth0-use-form-data", config.Config.Auth.Auth0.UseFormData,
"When true, data to the token endpoint is transmitted as x-www-form-urlencoded data instead of JSON. The default is false")

rootCmd.Flags().BoolVar(&config.Config.Auth.WebAuthn.Enabled, "auth-webauthn-enabled", config.Config.Auth.WebAuthn.Enabled,
"enable WebAuthn authentication. Once set to true, it cannot be set back to false.")
Expand Down
1 change: 1 addition & 0 deletions frontend/src/api/omni/specs/auth.pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type AuthConfigSpecAuth0 = {
enabled?: boolean
domain?: string
client_id?: string
useFormData?: boolean
}

export type AuthConfigSpecWebauthn = {
Expand Down
15 changes: 8 additions & 7 deletions frontend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,14 @@ const setupApp = async () => {
appendToBody: true,
})

if (authType.value === AuthType.Auth0) {
app = app.use(createAuth0({
domain: authConfigSpec!.auth0?.domain!,
client_id: authConfigSpec!.auth0?.client_id!,
redirect_uri: window.location.origin,
}))
}
if (authType.value === AuthType.Auth0) {
app = app.use(createAuth0({
domain: authConfigSpec!.auth0?.domain!,
client_id: authConfigSpec!.auth0?.client_id!,
redirect_uri: window.location.origin,
useFormData: !!authConfigSpec!.auth0?.useFormData,
}))
}

app.use(vClickOutside);
app.mount('#app');
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/auth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func EnsureAuthConfigResource(ctx context.Context, st state.State, logger *zap.L
res.TypedSpec().Value.Auth0.Enabled = authParams.Auth0.Enabled
res.TypedSpec().Value.Auth0.Domain = authParams.Auth0.Domain
res.TypedSpec().Value.Auth0.ClientId = authParams.Auth0.ClientID
res.TypedSpec().Value.Auth0.UseFormData = authParams.Auth0.UseFormData
res.TypedSpec().Value.Saml.Enabled = authParams.SAML.Enabled
res.TypedSpec().Value.Saml.Url = authParams.SAML.URL
res.TypedSpec().Value.Saml.Metadata = authParams.SAML.Metadata
Expand Down
7 changes: 4 additions & 3 deletions internal/pkg/config/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ type AuthParams struct {

// Auth0Params holds configuration parameters for Auth0.
type Auth0Params struct {
Domain string `yaml:"domain"`
ClientID string `yaml:"clientID"`
Enabled bool `yaml:"enabled"`
Domain string `yaml:"domain"`
ClientID string `yaml:"clientID"`
UseFormData bool `yaml:"useFormData"`
Enabled bool `yaml:"enabled"`
}

// WebAuthnParams holds configuration parameters for WebAuthn.
Expand Down

0 comments on commit 2e015a9

Please sign in to comment.