auth0 / terraform-provider-auth0

The Auth0 Terraform Provider is the official plugin for managing Auth0 tenant configuration through the Terraform tool.
https://registry.terraform.io/providers/auth0/auth0/latest/docs
Mozilla Public License 2.0
157 stars 73 forks source link

Incorrect token_endpoint_auth_method for SPA in Auth0 via Terraform #958

Closed Karthik6615 closed 1 month ago

Karthik6615 commented 1 month ago

Checklist

Description

Hi Terraform Team,

I'm encountering a bug with the token_endpoint_auth_method when deploying a Single Page Application (SPA) via Terraform.

When created via the Auth0 Dashboard, the token_endpoint_auth_method is correctly set to none. However, when deployed via Terraform, it is set to client_secret_post.

This seems related to a feature introduced in v1.1.0 of the Terraform Auth0 provider. Currently, we are using version 1.1.2 of the provider.

Please look into this issue. More details can be found: https://github.com/auth0/terraform-provider-auth0/releases.

Thank you, Karthik Thatipati

Screenshot 2024-05-17 at 12 22 05 PM Screenshot 2024-05-17 at 12 15 35 PM

Expectation

token_endpoint_auth_method should set to none, when creating auth0_client with app_type as spa

Reproduction

When created via the Auth0 Dashboard, the token_endpoint_auth_method is correctly set to none. However, when deployed via Terraform, it is set to client_secret_post.

This seems related to a feature introduced in v1.1.0 of the Terraform Auth0 provider. Currently, we are using version 1.1.2 of the provider.

Auth0 Terraform Provider version

1.1.2

Terraform version

1.5.4

developerkunal commented 1 month ago

Hey @Karthik6615,

Hope everything's going well for you! I've been tinkering with creating a resource of my own, and I'm wondering if you could lend a hand. Below is the example resource I've been working on. It seems to be functioning properly on my end:

resource "auth0_client" "frontend_client" {
  name        = "name"
  description = "description"

  client_metadata = {} // Feel free to insert your real values here

  app_type = "spa"

  // Fill in with your real values
  initiate_login_uri  = ""
  callbacks           = []
  allowed_origins     = []
  allowed_logout_urls = []
  web_origins         = []

  oidc_conformant = true
  logo_uri        = ""
  grant_types     = [
    "refresh_token",
    "authorization_code",
    "http://auth0.com/oauth/grant-type/mfa-otp"
  ]
  is_first_party  = true

  jwt_configuration {
    alg = "RS256"
  }

  refresh_token {
    rotation_type                = "rotating"
    expiration_type              = "expiring"
    token_lifetime               = 43200 // 12 hours
    idle_token_lifetime          = 28800 // 8 hours
    infinite_idle_token_lifetime = false
  }
}

If you have a similar example resource or any insights, could you please share it with me? I'd love to compare notes and gather more ideas. Thanks in advance!

thomaswienecke commented 1 month ago

I have the same problem as the issue opener. My "auth0_client" resource looks roughly like this:

resource "auth0_client" "..." {
  name                       = "..."
  description                = "..."
  app_type                   = "spa"
  callbacks                  = [var.base_url"]
  allowed_origins            = [var.base_url]
  web_origins                = [var.base_url]
  allowed_logout_urls        = [var.base_url]

  jwt_configuration {
    alg = "RS256"
  }

  grant_types = [
    "implicit",
    "authorization_code",
    "refresh_token",
    "http://auth0.com/oauth/grant-type/mfa-otp",
    "http://auth0.com/oauth/grant-type/mfa-recovery-code"
  ]
}

While the data source "auth0_client" has the option to specify token_endpoint_auth_method, I couldn't find an option to set it using the resource. And as the issue opener already mentioned, it should be set to none by default anyways when using an spa app_type.

P.s.: Found a working solution by adding another resource:

resource "auth0_client_credentials" "l..." {
  client_id = auth0_client.xxx.id

  authentication_method = "none"
}
developerkunal commented 1 month ago

Hey @Karthik6615,

Hope your day's going well.

Sorry for the confusion in my last message. Also, a big shoutout to @thomaswienecke for pitching in! Let me explain things a bit more clearly.

When you're creating a new Single Page Application (SPA), there's something important to note: for these new SPAs, the token_endpoint_auth_method is now set to none by default starting from provider version 1.1.0. Here's an example to make it clear:

Example :

resource "auth0_client" "frontend_client" {
  name        = "name"
  description = "description"

  client_metadata = {} // Feel free to insert your real values here

  app_type = "spa"

  // Fill in with your real values
  initiate_login_uri  = ""
  callbacks           = []
  allowed_origins     = []
  allowed_logout_urls = []
  web_origins         = []

  oidc_conformant = true
  logo_uri        = ""
  grant_types     = [
    "refresh_token",
    "authorization_code",
    "http://auth0.com/oauth/grant-type/mfa-otp"
  ]
  is_first_party  = true

  jwt_configuration {
    alg = "RS256"
  }

  refresh_token {
    rotation_type                = "rotating"
    expiration_type              = "expiring"
    token_lifetime               = 43200 // 12 hours
    idle_token_lifetime          = 28800 // 8 hours
    infinite_idle_token_lifetime = false
  }
}

However, if you're working with older provider versions (before 1.1.0), the default token_endpoint_auth_method is not set automatically. You'd need to use something like this:

Example :

resource "auth0_client" "frontend_client" {
  name        = "name"
  description = "description"

  client_metadata = {} // Feel free to insert your real values here

  app_type = "spa"

  // Fill in with your real values
  initiate_login_uri  = ""
  callbacks           = []
  allowed_origins     = []
  allowed_logout_urls = []
  web_origins         = []

  oidc_conformant = true
  logo_uri        = ""
  grant_types     = [
    "refresh_token",
    "authorization_code",
    "http://auth0.com/oauth/grant-type/mfa-otp"
  ]
  is_first_party  = true

  jwt_configuration {
    alg = "RS256"
  }

  refresh_token {
    rotation_type                = "rotating"
    expiration_type              = "expiring"
    token_lifetime               = 43200 // 12 hours
    idle_token_lifetime          = 28800 // 8 hours
    infinite_idle_token_lifetime = false
  }
}

resource "auth0_client_credentials" "test" {
  client_id = auth0_client.frontend_client.id

  authentication_method = "none"
}

By making this adjustment, it should sort out the issue you're facing. If there's anything else you need help with or if you run into more issues, just drop a comment or open a new issue. I'm here to assist however I can.

For more detailed information, you can check out the reference link here, where it maps to the token_endpoint_auth_method. Additionally, you can review the changelog for further details on this update.

Karthik6615 commented 1 month ago

Hi Kunal,

Thank you for the information. I wanted to share an observation I made. Even though it's a single-page application, we can set authentication_method = "client_secret_post" in the auth0_client_credentials resource. Additionally, if we set authentication_method to none, the auth0_client works as expected.

Best regards, Karthik Thatipati

developerkunal commented 1 month ago

Hi @Karthik6615 ,

I hope you're having a nice day!

Thanks for sharing your observation. It's interesting to note that even though it's a single-page application, we're able to set the authentication_method to "client_secret_post" in the auth0_client_credentials resource. Additionally, setting authentication_method to none seems to work as expected.


There's some subtlety here, but this behavior is expected. The dashboard has certain conventions and restrictions in place to guide developers towards safer and recommended setups. For single-page applications in the dashboard, we don't display a credentials tab since SPAs typically can't securely hold any credentials and should be treated as public clients with token_endpoint_auth_method set to none.

However, when using the management API, we allow more flexibility and freedom, enabling you to configure any authentication method. This backward compatibility feature allows you to configure an authentication method using the API. But it's worth noting that you might end up with an app tagged as an SPA, which might not align with its actual nature.

The key message here is that SPAs cannot securely hold credentials, so a SPA should only use token_endpoint_auth_method: none. Anything else is not recommended and should only be used in applications that can securely store a confidential credential.

Overall, things should continue to function as expected if you configure an authentication method using the API. However, it's essential to be mindful of the intended setup and the implications of the chosen authentication method.

If you have any questions or anything to ask, please feel free to do so here or create new issues.

Thank you!

developerkunal commented 1 month ago

Hi @Karthik6615 ,

I hope you're having a pleasant day!

I just wanted to inform you that I'll be closing this issue shortly. However, if you have any more issues or questions, please feel free to open a new one. I'm here to assist you further.

Best regards,