Skip to content

Commit

Permalink
feat(session): CHK-2935 add email to start session policy. set variab…
Browse files Browse the repository at this point in the history
…le to fragment code (#2130)

* feat(auth-fow-wallet): add common pagopa IO auth

* feat(ecomm-auth-io): new auth for eCommerce

* fix: token in ecommerce for io api

* fix wallet disalignment

* update openapi

* set v2 for ecommerce api

* add email to start session policy. set variable to fragment code

* feat(wallet-common & pay-wallet-common): add expiration storage queue (#2133)

* feat(wallet-common): add expiration storage queue

* fix: pre-commit

* feat: Migrated uat apim (#2135)

migrated uat apim

* feat: Switched to old apim v2 uat (#2136)

switched to old apim v2

* pre commit

* pre-commit

* restore wallet token into shared jwt token

* fix typo

* remove wallet token from shared session token claim

* named value to handle pm policies

* fix named value

* fix named value and policy

* rename policy file

* fix new wallet pèolicy

---------

Co-authored-by: Simone Infante <[email protected]>
Co-authored-by: Simone infante <[email protected]>
Co-authored-by: Gianluca Ciuffa <[email protected]>
Co-authored-by: Pietro Tota <[email protected]>
Co-authored-by: Marco Mari <[email protected]>
Co-authored-by: Giovanni Berti <[email protected]>
  • Loading branch information
7 people authored Jun 13, 2024
1 parent 6bec0fd commit abc6959
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 112 deletions.
8 changes: 8 additions & 0 deletions src/domains/shared-app/04_apim_io_wallet_session.tf
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ module "apim_session_wallet_product" {
#################################################
## API session wallet token pagoPA for IO ##
#################################################
resource "azurerm_api_management_named_value" "ecommerce_io_pm_enabled" {
name = "enable-pm-ecommerce-io"
api_management_name = local.pagopa_apim_name
resource_group_name = local.pagopa_apim_rg
display_name = "enable-pm-ecommerce-io"
value = var.ecommerce_io_pm_enabled
}

locals {
apim_session_wallet_api = {
display_name = "pagoPA - session wallet token pagoPA for IO APP"
Expand Down
6 changes: 6 additions & 0 deletions src/domains/shared-app/99_variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,10 @@ variable "pdv_api_base_path" {
type = string
default = null
description = "Personal data vault api base path"
}

variable "ecommerce_io_pm_enabled" {
type = bool
description = "eCommerce vs pm enabled"
default = false
}
2 changes: 2 additions & 0 deletions src/domains/shared-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
| [azurerm_api_management_api_version_set.api_taxonomy_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
| [azurerm_api_management_api_version_set.session_wallet_api](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_api_version_set) | resource |
| [azurerm_api_management_group.technical_support_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_group) | resource |
| [azurerm_api_management_named_value.ecommerce_io_pm_enabled](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_named_value) | resource |
| [azurerm_api_management_named_value.wallet-jwt-signing-key](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_named_value) | resource |
| [azurerm_api_management_named_value.wallet_personal_data_vault_api_key](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_named_value) | resource |
| [azurerm_api_management_product_group.technical_support_group_association](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_product_group) | resource |
Expand Down Expand Up @@ -169,6 +170,7 @@
| <a name="input_cname_record_name"></a> [cname\_record\_name](#input\_cname\_record\_name) | n/a | `string` | `"shared"` | no |
| <a name="input_dns_zone_internal_prefix"></a> [dns\_zone\_internal\_prefix](#input\_dns\_zone\_internal\_prefix) | The dns subdomain. | `string` | `null` | no |
| <a name="input_domain"></a> [domain](#input\_domain) | n/a | `string` | n/a | yes |
| <a name="input_ecommerce_io_pm_enabled"></a> [ecommerce\_io\_pm\_enabled](#input\_ecommerce\_io\_pm\_enabled) | eCommerce vs pm enabled | `bool` | `false` | no |
| <a name="input_env"></a> [env](#input\_env) | n/a | `string` | n/a | yes |
| <a name="input_env_short"></a> [env\_short](#input\_env\_short) | n/a | `string` | n/a | yes |
| <a name="input_external_domain"></a> [external\_domain](#input\_external\_domain) | Domain for delegation | `string` | `null` | no |
Expand Down
276 changes: 166 additions & 110 deletions src/domains/shared-app/api/session-wallet/v1/_base_policy.xml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,121 +2,177 @@
<inbound>
<base />
<set-variable name="walletToken" value="@(context.Request.Headers.GetValueOrDefault("Authorization", "").Replace("Bearer ",""))" />
<!-- Get User IO : START-->
<send-request ignore-error="true" timeout="10" response-variable-name="user-auth-body" mode="new">
<set-url>@("${io_backend_base_path}/pagopa/api/v1/user?version=20200114")</set-url>
<set-method>GET</set-method>
<set-header name="Accept" exists-action="override">
<value>application/json</value>
</set-header>
<set-header name="Authorization" exists-action="override">
<value>@("Bearer " + (string)context.Variables.GetValueOrDefault("walletToken"))</value>
</set-header>
</send-request>

<choose>
<when condition="@(((IResponse)context.Variables["user-auth-body"]).StatusCode == 401)">
<return-response>
<set-status code="401" reason="Unauthorized" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
{
"title": "Unauthorized",
"status": 401,
"detail": "Invalid session token"
}
</set-body>
</return-response>
<when condition="@("true".Equals("{{enable-pm-ecommerce-io}}"))">
<!-- Session PM START-->
<send-request ignore-error="true" timeout="10" response-variable-name="pm-session-body" mode="new">
<set-url>@($"{{pm-host}}/pp-restapi-CD/v1/users/actions/start-session?token={(string)context.Variables["walletToken"]}")</set-url>
<set-method>GET</set-method>
</send-request>
<choose>
<when condition="@(((IResponse)context.Variables["pm-session-body"]).StatusCode == 401)">
<return-response>
<set-status code="401" reason="Unauthorized" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
{
"title": "Unauthorized",
"status": 401,
"detail": "Invalid session token"
}
</set-body>
</return-response>
</when>
<when condition="@(((IResponse)context.Variables["pm-session-body"]).StatusCode != 200)">
<return-response>
<set-status code="502" reason="Bad Gateway" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
{
"title": "Error starting session",
"status": 502,
"detail": "There was an error starting session for input wallet token"
}
</set-body>
</return-response>
</when>
</choose>
<set-variable name="pmSession" value="@(((IResponse)context.Variables["pm-session-body"]).Body.As<JObject>())" />
<!-- Session PM END-->
<!-- pagoPA platform wallet JWT session token : START -->
<set-variable name="x-jwt-token" value="@(((JObject)context.Variables["pmSession"])["data"]["sessionToken"].ToString())" />
<!-- pagoPA platform wallet JWT session token : END -->
</when>
<when condition="@(((IResponse)context.Variables["user-auth-body"]).StatusCode != 200)">
<return-response>
<set-status code="502" reason="Bad Gateway" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
{
"title": "Error starting session",
"status": 502,
"detail": "There was an error while getting user info"
}
</set-body>
</return-response>
</when>
</choose>
<set-variable name="userAuth" value="@(((IResponse)context.Variables["user-auth-body"]).Body.As<JObject>())" />
<!-- Get User IO : END-->
<!-- Post Token PDV : START-->
<send-request ignore-error="true" timeout="10" response-variable-name="pdv-token" mode="new">
<set-url>${pdv_api_base_path}/tokens</set-url>
<set-method>PUT</set-method>
<set-header name="x-api-key" exists-action="override">
<value>{{wallet-session-personal-data-vault-api-key}}</value>
</set-header>
<set-body>@{
JObject requestBody = (JObject)context.Variables["userAuth"];
return new JObject(
new JProperty("pii", (string)requestBody["fiscal_code"])
).ToString();
}</set-body>
</send-request>
<choose>
<when condition="@(((IResponse)context.Variables["pdv-token"]).StatusCode != 200)">
<return-response>
<set-status code="502" reason="Bad Gateway" />
</return-response>
</when>
</choose>
<otherwise>
<!-- Get User IO : START-->
<send-request ignore-error="true" timeout="10" response-variable-name="user-auth-body" mode="new">
<set-url>@("${io_backend_base_path}/pagopa/api/v1/user?version=20200114")</set-url>
<set-method>GET</set-method>
<set-header name="Accept" exists-action="override">
<value>application/json</value>
</set-header>
<set-header name="Authorization" exists-action="override">
<value>@("Bearer " + (string)context.Variables.GetValueOrDefault("walletToken"))</value>
</set-header>
</send-request>
<choose>
<when condition="@(((IResponse)context.Variables["user-auth-body"]).StatusCode == 401)">
<return-response>
<set-status code="401" reason="Unauthorized" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
{
"title": "Unauthorized",
"status": 401,
"detail": "Invalid session token"
}
</set-body>
</return-response>
</when>
<when condition="@(((IResponse)context.Variables["user-auth-body"]).StatusCode != 200)">
<return-response>
<set-status code="502" reason="Bad Gateway" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
{
"title": "Error starting session",
"status": 502,
"detail": "There was an error while getting user info"
}
</set-body>
</return-response>
</when>
</choose>
<set-variable name="userAuthBody" value="@(((IResponse)context.Variables["user-auth-body"]).Body.As<JObject>())" />
<!-- Get User IO : END-->
<!-- Post Token PDV : START-->
<send-request ignore-error="true" timeout="10" response-variable-name="pdv-token" mode="new">
<set-url>${pdv_api_base_path}/tokens</set-url>
<set-method>PUT</set-method>
<set-header name="x-api-key" exists-action="override">
<value>{{wallet-session-personal-data-vault-api-key}}</value>
</set-header>
<set-body>@{
JObject requestBody = (JObject)context.Variables["userAuthBody"];
return new JObject(
new JProperty("pii", (string)requestBody["fiscal_code"])
).ToString();
}</set-body>
</send-request>
<choose>
<when condition="@(((IResponse)context.Variables["pdv-token"]).StatusCode != 200)">
<return-response>
<set-status code="502" reason="Bad Gateway" />
</return-response>
</when>
</choose>

<set-variable name="pdvToken" value="@(((IResponse)context.Variables["pdv-token"]).Body.As<JObject>())" />
<!-- used as jwt claims https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims -->
<set-variable name="userId" value="@((string)((JObject)context.Variables["pdvToken"])["token"])" />
<choose>
<when condition="@(String.IsNullOrEmpty((string)context.Variables["userId"]))">
<return-response>
<set-status code="502" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@{
return new JObject(
new JProperty("title", "Bad gateway - Invalid PDV response"),
new JProperty("status", 502),
new JProperty("detail", "Cannot tokenize fiscal code")
).ToString();
}</set-body>
</return-response>
</when>
</choose>
<!-- Post Token PDV : END-->
<set-variable name="pdvToken" value="@(((IResponse)context.Variables["pdv-token"]).Body.As<JObject>())" />
<!-- used as jwt claims https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims -->
<set-variable name="userId" value="@((string)((JObject)context.Variables["pdvToken"])["token"])" />
<choose>
<when condition="@(String.IsNullOrEmpty((string)context.Variables["userId"]))">
<return-response>
<set-status code="502" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@{
return new JObject(
new JProperty("title", "Bad gateway - Invalid PDV response"),
new JProperty("status", 502),
new JProperty("detail", "Cannot tokenize fiscal code")
).ToString();
}</set-body>
</return-response>
</when>
</choose>
<!-- Post Token PDV : END-->

<!-- pagoPA platform wallet JWT session token : START -->
<!-- Token JWT START-->
<set-variable name="x-jwt-token" value="@{
// Construct the Base64Url-encoded header
var header = new { typ = "JWT", alg = "HS512" };
var jwtHeaderBase64UrlEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header))).Replace("/", "_").Replace("+", "-"). Replace("=", "");
<!-- pagoPA platform wallet JWT session token : START -->
<!-- Token JWT START-->
<set-variable name="x-jwt-token" value="@{
//Construct the Base64Url-encoded header
var header = new { typ = "JWT", alg = "HS512" };
var jwtHeaderBase64UrlEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header))).Replace("/", "_").Replace("+", "-"). Replace("=", "");
// Construct the Base64Url-encoded payload
var jti = Guid.NewGuid().ToString(); //sets the iat claim. Random uuid added to prevent the reuse of this token
var date = DateTime.Now;
var iat = new DateTimeOffset(date).ToUnixTimeSeconds(); // sets the issued time of the token now
var exp = new DateTimeOffset(date.AddMinutes(20)).ToUnixTimeSeconds(); // sets the expiration of the token to be 20 minutes from now
String userId = ((string)context.Variables.GetValueOrDefault("userId",""));
// Read email and pass it to the JWT. By now the email in shared as is. It MUST be encoded (by pdv) but POST transaction need to updated to not match email address as email field
JObject userAuth = (JObject)context.Variables["userAuthBody"];
String spidEmail = (String)userAuth["spid_email"];
String noticeEmail = (String)userAuth["notice_email"];
String email = String.IsNullOrEmpty(noticeEmail) ? spidEmail : noticeEmail;
var payload = new { iat, exp, jti, email, userId};
var jwtPayloadBase64UrlEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload))).Replace("/", "_").Replace("+", "-"). Replace("=", "");
// Construct the Base64Url-encoded signature
var signature = new HMACSHA512(Convert.FromBase64String("{{wallet-session-jwt-signing-key}}")).ComputeHash(Encoding.UTF8.GetBytes($"{jwtHeaderBase64UrlEncoded}.{jwtPayloadBase64UrlEncoded}"));
var jwtSignatureBase64UrlEncoded = Convert.ToBase64String(signature).Replace("/", "_").Replace("+", "-"). Replace("=", "");
// 2) Construct the Base64Url-encoded payload
var jti = Guid.NewGuid().ToString(); //sets the iat claim. Random uuid added to prevent the reuse of this token
var date = DateTime.Now;
var iat = new DateTimeOffset(date).ToUnixTimeSeconds(); // sets the issued time of the token now
var exp = new DateTimeOffset(date.AddMinutes(20)).ToUnixTimeSeconds(); // sets the expiration of the token to be 20 minutes from now
var userId = ((string)context.Variables.GetValueOrDefault("userId",""));
var walletId = ((string)context.Variables.GetValueOrDefault("walletToken",""));
var payload = new { iat, exp, jti, userId, walletId };
var jwtPayloadBase64UrlEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload))).Replace("/", "_").Replace("+", "-"). Replace("=", "");
// 3) Construct the Base64Url-encoded signature
var signature = new HMACSHA512(Convert.FromBase64String("{{wallet-session-jwt-signing-key}}")).ComputeHash(Encoding.UTF8.GetBytes($"{jwtHeaderBase64UrlEncoded}.{jwtPayloadBase64UrlEncoded}"));
var jwtSignatureBase64UrlEncoded = Convert.ToBase64String(signature).Replace("/", "_").Replace("+", "-"). Replace("=", "");
// 4) Return the HMAC SHA512-signed JWT as the value for the Authorization header
return $"{jwtHeaderBase64UrlEncoded}.{jwtPayloadBase64UrlEncoded}.{jwtSignatureBase64UrlEncoded}";
}" />
<!-- Token JWT END-->
<!-- pagoPA platform wallet JWT session token : END -->
// Return the HMAC SHA512-signed JWT as the value for the Authorization header
return $"{jwtHeaderBase64UrlEncoded}.{jwtPayloadBase64UrlEncoded}.{jwtSignatureBase64UrlEncoded}";
}" />
<!-- Token JWT END-->
<!-- pagoPA platform wallet JWT session token : END -->
</otherwise>
</choose>


<return-response>
<set-status code="201" />
Expand Down
Loading

0 comments on commit abc6959

Please sign in to comment.