Skip to content

Commit

Permalink
add the support for every possible issuer in Single Tenant for emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
JhontSouth committed Jan 7, 2025
1 parent 242995d commit 2a037dd
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;

namespace Microsoft.Bot.Connector.Authentication
Expand Down Expand Up @@ -77,9 +78,13 @@ public static bool IsTokenFromEmulator(string authHeader)
{
//If the issuer doesn't exist, this is added using the Emulator token issuer structure.
//This allows use of the SingleTenant authentication through Emulator.
var newIssuer = AuthenticationConstants.ValidTokenIssuerUrlTemplateV1.Replace("{0}", tenantId);
ToBotFromEmulatorTokenValidationParameters.ValidIssuers =
ToBotFromEmulatorTokenValidationParameters.ValidIssuers.Concat(new string[] { newIssuer });
var validTokenIssuers = new List<string>();
validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV1, tenantId));
validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV2, tenantId));
validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV1, tenantId));
validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV2, tenantId));

ToBotFromEmulatorTokenValidationParameters.ValidIssuers = validTokenIssuers;
}

// Is the token issues by a source we consider to be the emulator?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.IdentityModel.Tokens;
using Xunit;

namespace Microsoft.Bot.Connector.Tests.Authentication
{
public class EmulatorValidationTests
{
[Fact]
public void IsTokenFromEmulator_ShouldReturnFalseOnTokenBadFormat()
{
//Token with bad format is not processed
var authHeader = string.Empty;
Assert.False(EmulatorValidation.IsTokenFromEmulator(authHeader));

//If the token doesn't contain an issuer value it returns false
authHeader = GenerateMockBearerToken(null);
Assert.False(EmulatorValidation.IsTokenFromEmulator(authHeader));
}

[Fact]
public void IsTokenFromEmulator_ShouldReturnFalseOnInvalidTokenIssuer()
{
var authHeader = GenerateMockBearerToken("https://mockIssuer.com");
Assert.False(EmulatorValidation.IsTokenFromEmulator(authHeader));
}

[Fact]
public void IsTokenFromEmulator_ShouldReturnTrueOnValidTokenIssuer()
{
//Validate issuer with V1 Token
var authHeader = GenerateMockBearerToken(AuthenticationConstants.ValidTokenIssuerUrlTemplateV1);
Assert.True(EmulatorValidation.IsTokenFromEmulator(authHeader));

//Validate issuer with V2 Token
authHeader = GenerateMockBearerToken(AuthenticationConstants.ValidTokenIssuerUrlTemplateV2);
Assert.True(EmulatorValidation.IsTokenFromEmulator(authHeader));

//Validate Government issuer with V1 Token
authHeader = GenerateMockBearerToken(AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV1);
Assert.True(EmulatorValidation.IsTokenFromEmulator(authHeader));

//Validate Government issuer with V2 Token
authHeader = GenerateMockBearerToken(AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV2);
Assert.True(EmulatorValidation.IsTokenFromEmulator(authHeader));
}

private string GenerateMockBearerToken(string issuer)
{
var key = Encoding.UTF8.GetBytes("ThisIsASuperMockSecretKey123456789");
var signingKey = new SymmetricSecurityKey(key);
var tenantId = Guid.NewGuid().ToString();

var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = issuer?.Replace("{0}", tenantId),
Audience = "https://api.example.com",
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "John Doe"),
new Claim(ClaimTypes.Role, "Admin"),
new Claim("tid", tenantId)
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature)
};

// Create and return the JWT
var token = tokenHandler.CreateToken(tokenDescriptor);
return $"Bearer {tokenHandler.WriteToken(token)}";
}
}
}

0 comments on commit 2a037dd

Please sign in to comment.