The Partner Portal's IntegrationServiceAPI receives incoming work order messages from a legacy WCF (Windows Communication Foundation) service. This service uses a pre-configured static JWT token for authentication instead of dynamic Azure AD tokens.
Key Characteristics:
Source/EGU.PartnerPortal.IntegrationServiceAPISource/EGU.PartnerPortal.IntegrationServiceAPI/Services/Middleware/AuthenticationConfiguration.csSource/EGU.PartnerPortal.IntegrationServiceAPI/Controller/IncomingTrafficController.cs/api/ReceiveWCFIncomingMessage┌─────────────────────────────────────────────────────────────────┐
│ WCF SERVICE STATIC TOKEN AUTHENTICATION │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────┐
│ WCF Service │
│ (External legacy system) │
└──────┬───────────────────────┘
│
│ Has static JWT token
│ configured in settings
│
│ Step 1: Prepare message
│ - ClientID
│ - XML Data (byte[])
│ - MessageType
▼
┌──────────────────────────────────┐
│ HTTP Request │
│ POST /api/ReceiveWCFIncoming... │
│ Authorization: Bearer eyJ0eX... │
│ Body: IncomingMessageRequest │
└──────┬───────────────────────────┘
│
│ Step 2: Request arrives
▼
┌──────────────────────────────────┐
│ IntegrationServiceAPI │
│ Multi-Scheme Authenticator │
└──────┬───────────────────────────┘
│
│ Step 3: Read token & route
│ Parse JWT token:
│ - Issuer: "PartnerPortal"?
│ - Claim: service_name="WCFservice"?
│ - Path: /api/ReceiveWCFIncoming...?
│
├─── All Valid ───┐ Invalid ────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Route to │ │ Validate │ │ 401 │
│ StaticToken │ │ Token │ │ Unauthorized│
│ Scheme │ │ │ │ │
└──────────────┘ └──────┬───────┘ └──────────────┘
│
│ Step 4: Token validation
│ - Signature (HS256 symmetric key)
│ - Issuer = "PartnerPortal"
│ - Audience = "EGU.PartnerPortal"
│ - Lifetime (if expiration set)
│
├─── Valid ────┐
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Forward to │ │ 200 OK │
│ Controller │ │ │
└──────┬───────┘ └──────────────┘
│
│ Step 5: Process message
▼
┌──────────────────────┐
│ IncomingTraffic │
│ Controller │
└──────┬───────────────┘
│
│ Step 6: Decode & validate XML
│ Step 7: Call ApiService
│ Step 8: Return response
▼
┌──────────────────────┐
│ Success response │
│ sent to WCF │
└──────────────────────┘
The static JWT token is a standard JSON Web Token with three parts:
Header:
{
"alg": "HS256",
"typ": "JWT"
}
Payload (Claims):
{
"iss": "PartnerPortal",
"aud": "EGU.PartnerPortal",
"service_name": "WCFservice",
"exp": 1893456000,
"iat": 1733456000
}
Signature:
||Claim||Type||Value||Description|| |iss|String|"PartnerPortal"|Issuer - identifies token source| |aud|String|"EGU.PartnerPortal"|Audience - identifies intended recipient| |service_name|String|"WCFservice"|Custom claim identifying WCF service| |exp|Numeric|Unix timestamp|Expiration time (optional but recommended)| |iat|Numeric|Unix timestamp|Issued at time (optional)|
The WCF service must generate the JWT token using the shared secret key:
// Pseudocode - WCF service implementation
var secretKey = "<base64-encoded-secret-key>";
var signingKey = new SymmetricSecurityKey(Convert.FromBase64String(secretKey));
var credentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim("iss", "PartnerPortal"),
new Claim("aud", "EGU.PartnerPortal"),
new Claim("service_name", "WCFservice")
};
var token = new JwtSecurityToken(
issuer: "PartnerPortal",
audience: "EGU.PartnerPortal",
claims: claims,
expires: DateTime.UtcNow.AddYears(10), // Long-lived token
signingCredentials: credentials
);
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
// Store tokenString in Azure environment variable
File: appsettings.json
{
"AccessToken": {
"SecretKey": "<base64-encoded-secret-key>"
}
}
Secret Key:
Location: IntegrationServiceAPI/Services/Middleware/AuthenticationConfiguration.cs:148-177
The middleware configures three authentication schemes:
StaticTokenScheme Configuration:
.AddJwtBearer(AuthenticationConstants.StaticTokenScheme, opts =>
{
var secretKey = configuration["AccessToken:SecretKey"]?.Trim().TrimEnd(',');
var signingKey = new SymmetricSecurityKey(Convert.FromBase64String(secretKey));
opts.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "PartnerPortal",
ValidateAudience = true,
ValidAudience = "EGU.PartnerPortal",
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
ClockSkew = TimeSpan.FromMinutes(5)
};
});
Static tokens are ONLY valid for this endpoint:
/api/ReceiveWCFIncomingMessageEnforcement Logic:
private static readonly string[] AllowedWcfEndpoints = new[]
{
"/api/ReceiveWCFIncomingMessage"
};
private static bool IsAllowedWcfEndpoint(PathString requestPath)
{
return AllowedWcfEndpoints.Any(endpoint =>
requestPath.StartsWithSegments(endpoint, StringComparison.OrdinalIgnoreCase));
}
Path Validation Flow:
Security Benefit:
What happens:
IncomingMessageRequest with XML dataWho's involved:
Result:
What happens:
Who's involved:
Result:
What happens:
/api/ReceiveWCFIncomingMessage?Who's involved:
Result:
What happens:
Who's involved:
What's validated:
Result:
What happens:
IncomingTrafficController.ReceiveWCFIncomingMessageWho's involved:
Result:
What happens:
Who's involved:
Result: