Skip to content

Commit b86b54d

Browse files
authored
Add migration steps for JWT/OAuth/OpenID Connect/Certificates (#403)
1 parent 0537f20 commit b86b54d

File tree

1 file changed

+387
-1
lines changed

1 file changed

+387
-1
lines changed

docs/docs/v4/welcome/migrate-quick-steps.md

Lines changed: 387 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,393 @@ For additional information, see the updated [Security documentation](../security
12511251
The CredHub client has been removed from Steeltoe in v4.
12521252
Use [CredHub Service Broker](https://techdocs.broadcom.com/us/en/vmware-tanzu/platform-services/credhub-service-broker/services/credhub-sb/index.html) instead.
12531253

1254-
### TODO: JWT/OAuth/OpenID Connect/Certificates...
1254+
### OAuth
1255+
1256+
OAuth support has been removed from Steeltoe in v4. Use OpenID Connect instead.
1257+
1258+
Before migrating to Steeltoe v4, apply the following changes to migrate from OAuth to OpenID Connect using Steeltoe v3.
1259+
1260+
appsettings.json:
1261+
1262+
```diff
1263+
{
1264+
"$schema": "https://steeltoe.io/schema/v3/schema.json",
1265+
"Security": {
1266+
"Oauth2": {
1267+
"Client": {
1268+
- "AuthDomain": "http://localhost:8080",
1269+
+ "Authority": "http://localhost:8080",
1270+
+ "MetadataAddress": "http://localhost:8080/.well-known/openid-configuration",
1271+
+ "RequireHttpsMetadata": false,
1272+
+ "AdditionalScopes": "sampleapi.read",
1273+
"CallbackPath": "/signin-oidc",
1274+
"ClientId": "steeltoesamplesclient",
1275+
"ClientSecret": "client_secret"
1276+
}
1277+
}
1278+
}
1279+
}
1280+
```
1281+
1282+
> [!NOTE]
1283+
> Depending on your application's needs, you may need to add scopes to the application's configuration that did not previously need to be specified.
1284+
1285+
program.cs:
1286+
1287+
```diff
1288+
using Microsoft.AspNetCore.Authentication.Cookies;
1289+
using Microsoft.AspNetCore.HttpOverrides;
1290+
using Steeltoe.Extensions.Configuration.CloudFoundry;
1291+
using Steeltoe.Security.Authentication.CloudFoundry;
1292+
1293+
var builder = WebApplication.CreateBuilder(args);
1294+
builder.AddCloudFoundryConfiguration();
1295+
builder.Services.AddAuthentication(options =>
1296+
{
1297+
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
1298+
options.DefaultChallengeScheme = CloudFoundryDefaults.AuthenticationScheme;
1299+
})
1300+
.AddCookie(options => options.AccessDeniedPath = new PathString("/Home/AccessDenied"))
1301+
- .AddCloudFoundryOAuth(builder.Configuration);
1302+
+ .AddCloudFoundryOpenIdConnect(builder.Configuration);
1303+
builder.Services.AddAuthorizationBuilder()
1304+
.AddPolicy("read", policy => policy.RequireClaim("scope", "sampleapi.read"));
1305+
1306+
var app = builder.Build();
1307+
1308+
app.UseForwardedHeaders(new ForwardedHeadersOptions
1309+
{
1310+
ForwardedHeaders = ForwardedHeaders.XForwardedProto
1311+
});
1312+
1313+
app.UseAuthentication();
1314+
app.UseAuthorization();
1315+
1316+
app.MapGet("/test-auth", async httpContext =>
1317+
{
1318+
httpContext.Response.StatusCode = 200;
1319+
httpContext.Response.ContentType = "text/plain";
1320+
await httpContext.Response.WriteAsync("You are logged in and carry the required claim.");
1321+
}).RequireAuthorization("read");
1322+
1323+
app.Run();
1324+
```
1325+
1326+
### OpenID Connect
1327+
1328+
Project file:
1329+
1330+
```diff
1331+
<Project>
1332+
<ItemGroup>
1333+
- <PackageReference Include="Steeltoe.Extensions.Configuration.CloudFoundryCore" Version="3.*" />
1334+
+ <PackageReference Include="Steeltoe.Configuration.CloudFoundry" Version="4.0.0" />
1335+
- <PackageReference Include="Steeltoe.Security.Authentication.CloudFoundryCore" Version="3.*" />
1336+
+ <PackageReference Include="Steeltoe.Security.Authentication.OpenIdConnect" Version="4.0.0" />
1337+
</ItemGroup>
1338+
</Project>
1339+
```
1340+
1341+
appsettings.json:
1342+
1343+
```diff
1344+
{
1345+
- "$schema": "https://steeltoe.io/schema/v3/schema.json",
1346+
+ "$schema": "https://steeltoe.io/schema/v4/schema.json",
1347+
- "Security": {
1348+
- "Oauth2": {
1349+
- "Client": {
1350+
- "Authority": "http://localhost:8080",
1351+
- "MetadataAddress": "http://localhost:8080/.well-known/openid-configuration",
1352+
- "RequireHttpsMetadata": false,
1353+
- "AdditionalScopes": "sampleapi.read",
1354+
- "CallbackPath": "/signin-oidc",
1355+
- "ClientId": "steeltoesamplesclient",
1356+
- "ClientSecret": "client_secret"
1357+
- }
1358+
- }
1359+
- }
1360+
+ "Authentication": {
1361+
+ "Schemes": {
1362+
+ "OpenIdConnect": {
1363+
+ "Authority": "http://localhost:8080",
1364+
+ "MetadataAddress": "http://localhost:8080/.well-known/openid-configuration",
1365+
+ "RequireHttpsMetadata": false,
1366+
+ "Scope": [ "openid", "sampleapi.read" ],
1367+
+ "CallbackPath": "/signin-oidc",
1368+
+ "ClientId": "steeltoesamplesclient",
1369+
+ "ClientSecret": "client_secret"
1370+
+ }
1371+
+ }
1372+
+ }
1373+
}
1374+
```
1375+
1376+
> [!NOTE]
1377+
> This is not a complete listing of appsettings. As of version 4, Steeltoe configures Microsoft's option class rather than maintaining separate options.
1378+
> Refer to [the OpenIdConnectOptions class documentation](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.authentication.openidconnect.openidconnectoptions) for the new options.
1379+
1380+
Program.cs:
1381+
1382+
```diff
1383+
using Microsoft.AspNetCore.Authentication.Cookies;
1384+
-using Microsoft.AspNetCore.HttpOverrides;
1385+
-using Steeltoe.Extensions.Configuration.CloudFoundry;
1386+
+using Steeltoe.Configuration.CloudFoundry;
1387+
+using Steeltoe.Configuration.CloudFoundry.ServiceBindings;
1388+
-using Steeltoe.Security.Authentication.CloudFoundry;
1389+
+using Microsoft.AspNetCore.Authentication.OpenIdConnect;
1390+
+using Steeltoe.Security.Authentication.OpenIdConnect;
1391+
1392+
var builder = WebApplication.CreateBuilder(args);
1393+
builder.AddCloudFoundryConfiguration();
1394+
+builder.Configuration.AddCloudFoundryServiceBindings();
1395+
builder.Services.AddAuthentication(options =>
1396+
{
1397+
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
1398+
- options.DefaultChallengeScheme = CloudFoundryDefaults.AuthenticationScheme;
1399+
+ options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
1400+
})
1401+
.AddCookie(options => options.AccessDeniedPath = new PathString("/Home/AccessDenied"))
1402+
- .AddCloudFoundryOpenIdConnect(builder.Configuration);
1403+
+ .AddOpenIdConnect().ConfigureOpenIdConnectForCloudFoundry();
1404+
builder.Services.AddAuthorizationBuilder()
1405+
.AddPolicy("read", policy => policy.RequireClaim("scope", "sampleapi.read"));
1406+
1407+
var app = builder.Build();
1408+
1409+
-app.UseForwardedHeaders(new ForwardedHeadersOptions
1410+
-{
1411+
- ForwardedHeaders = ForwardedHeaders.XForwardedProto
1412+
-});
1413+
1414+
app.UseAuthentication();
1415+
app.UseAuthorization();
1416+
1417+
app.MapGet("/test-auth", async httpContext =>
1418+
{
1419+
httpContext.Response.StatusCode = 200;
1420+
httpContext.Response.ContentType = "text/plain";
1421+
await httpContext.Response.WriteAsync("You are logged in and carry the required claim.");
1422+
}).RequireAuthorization("read");
1423+
1424+
app.Run();
1425+
```
1426+
1427+
### JWT Bearer
1428+
1429+
Project file:
1430+
1431+
```diff
1432+
<Project>
1433+
<ItemGroup>
1434+
- <PackageReference Include="Steeltoe.Extensions.Configuration.CloudFoundryCore" Version="3.*" />
1435+
+ <PackageReference Include="Steeltoe.Configuration.CloudFoundry" Version="4.0.0" />
1436+
- <PackageReference Include="Steeltoe.Security.Authentication.CloudFoundryCore" Version="3.*" />
1437+
+ <PackageReference Include="Steeltoe.Security.Authentication.JwtBearer" Version="4.0.0" />
1438+
</ItemGroup>
1439+
</Project>
1440+
```
1441+
1442+
appsettings.json:
1443+
1444+
```diff
1445+
{
1446+
- "$schema": "https://steeltoe.io/schema/v3/schema.json",
1447+
+ "$schema": "https://steeltoe.io/schema/v4/schema.json",
1448+
- "Security": {
1449+
- "Oauth2": {
1450+
- "Client": {
1451+
- "AuthDomain": "http://localhost:8080",
1452+
- "MetadataAddress": "http://localhost:8080/.well-known/openid-configuration",
1453+
- "RequireHttpsMetadata": false,
1454+
- "ClientId": "steeltoesamplesserver",
1455+
- "ClientSecret": "server_secret"
1456+
- }
1457+
- }
1458+
- }
1459+
+ "Authentication": {
1460+
+ "Schemes": {
1461+
+ "Bearer": {
1462+
+ "Authority": "http://localhost:8080",
1463+
+ "MetadataAddress": "http://localhost:8080/.well-known/openid-configuration",
1464+
+ "RequireHttpsMetadata": false,
1465+
+ "ClientId": "steeltoesamplesserver",
1466+
+ "ClientSecret": "server_secret",
1467+
+ "ValidAudiences": [ "sampleapi" ]
1468+
+ }
1469+
+ }
1470+
+ }
1471+
}
1472+
```
1473+
1474+
> [!NOTE]
1475+
> This is not a complete listing of appsettings. As of version 4, Steeltoe configures Microsoft's option class rather than maintaining separate options.
1476+
> Refer to [the JwtBearerOptions class documentation](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.authentication.jwtbearer.jwtbeareroptions) for the new options.
1477+
1478+
Program.cs:
1479+
1480+
```diff
1481+
-using Microsoft.AspNetCore.HttpOverrides;
1482+
-using Steeltoe.Extensions.Configuration.CloudFoundry;
1483+
+using Steeltoe.Configuration.CloudFoundry;
1484+
+using Steeltoe.Configuration.CloudFoundry.ServiceBindings;
1485+
-using Steeltoe.Security.Authentication.CloudFoundry;
1486+
+using Steeltoe.Security.Authentication.JwtBearer;
1487+
1488+
var builder = WebApplication.CreateBuilder(args);
1489+
1490+
builder.AddCloudFoundryConfiguration();
1491+
+builder.Configuration.AddCloudFoundryServiceBindings();
1492+
builder.Services.AddAuthentication()
1493+
- .AddCloudFoundryJwtBearer(builder.Configuration);
1494+
+ .AddJwtBearer().ConfigureJwtBearerForCloudFoundry();
1495+
builder.Services.AddAuthorizationBuilder()
1496+
.AddPolicy("sampleapi.read", policy => policy.RequireClaim("scope", "sampleapi.read"));
1497+
1498+
var app = builder.Build();
1499+
1500+
-app.UseForwardedHeaders(new ForwardedHeadersOptions
1501+
-{
1502+
- ForwardedHeaders = ForwardedHeaders.XForwardedProto
1503+
-});
1504+
1505+
app.UseAuthentication();
1506+
app.UseAuthorization();
1507+
1508+
app.MapGet("/test-jwt", async httpContext =>
1509+
{
1510+
httpContext.Response.StatusCode = 200;
1511+
httpContext.Response.ContentType = "text/plain";
1512+
await httpContext.Response.WriteAsync("JWT is valid and contains the required claim.");
1513+
}).RequireAuthorization("sampleapi.read");
1514+
1515+
app.Run();
1516+
```
1517+
1518+
### Client Certificates (Mutual TLS)
1519+
1520+
Project file:
1521+
1522+
```diff
1523+
<Project>
1524+
<ItemGroup>
1525+
- <PackageReference Include="Steeltoe.Security.Authentication.CloudFoundryCore" Version="3.*" />
1526+
+ <PackageReference Include="Steeltoe.Security.Authorization.Certificate" Version="4.0.0" />
1527+
</ItemGroup>
1528+
</Project>
1529+
```
1530+
1531+
launchsettings.json (server-side):
1532+
1533+
```diff
1534+
{
1535+
"profiles": {
1536+
"http": {
1537+
"commandName": "Project",
1538+
"applicationUrl": "https://localhost:7107"
1539+
}
1540+
}
1541+
}
1542+
```
1543+
1544+
Program.cs (server-side):
1545+
1546+
```diff
1547+
+using Steeltoe.Common.Certificates;
1548+
-using Steeltoe.Security.Authentication.CloudFoundry;
1549+
+using Steeltoe.Security.Authorization.Certificate;
1550+
1551+
const string orgId = "a8fef16f-94c0-49e3-aa0b-ced7c3da6229";
1552+
const string spaceId = "122b942a-d7b9-4839-b26e-836654b9785f";
1553+
1554+
var builder = WebApplication.CreateBuilder(args);
1555+
-builder.Configuration.AddCloudFoundryContainerIdentity(orgId, spaceId);
1556+
+builder.Configuration.AddAppInstanceIdentityCertificate(new Guid(orgId), new Guid(spaceId));
1557+
-builder.Services.AddCloudFoundryCertificateAuth(options => options.CertificateHeader = "X-Forwarded-Client-Cert");
1558+
+builder.Services.AddAuthentication().AddCertificate();
1559+
+builder.Services.AddAuthorizationBuilder().AddOrgAndSpacePolicies("X-Forwarded-Client-Cert");
1560+
1561+
var app = builder.Build();
1562+
1563+
-app.UseCloudFoundryCertificateAuth();
1564+
+app.UseCertificateAuthorization();
1565+
1566+
app.MapGet("/test-same-org", async httpContext =>
1567+
{
1568+
httpContext.Response.StatusCode = 200;
1569+
httpContext.Response.ContentType = "text/plain";
1570+
await httpContext.Response.WriteAsync("Client and server identity certificates have matching Org values.");
1571+
})
1572+
- .RequireAuthorization(CloudFoundryDefaults.SameOrganizationAuthorizationPolicy);
1573+
+ .RequireAuthorization(CertificateAuthorizationPolicies.SameOrg);
1574+
app.MapGet("/test-same-space", async httpContext =>
1575+
{
1576+
httpContext.Response.StatusCode = 200;
1577+
httpContext.Response.ContentType = "text/plain";
1578+
await httpContext.Response.WriteAsync("Client and server identity certificates have matching Space values.");
1579+
})
1580+
- .RequireAuthorization(CloudFoundryDefaults.SameSpaceAuthorizationPolicy);
1581+
+ .RequireAuthorization(CertificateAuthorizationPolicies.SameSpace);
1582+
1583+
app.Run();
1584+
```
1585+
1586+
> [!NOTE]
1587+
> Prior to Steeltoe 3.3.0, Steeltoe Certificate Auth used the header `X-Forwarded-Client-Cert`, which was not configurable.
1588+
> The code shown above is provided for compatibility between the versions. The preferred header name is `X-Client-Cert`.
1589+
> In Steeltoe 4.0, the default header is `X-Client-Cert`, so the parameter can be omitted if cross-compatibility is not required.
1590+
1591+
Program.cs (client-side):
1592+
1593+
```diff
1594+
-using System.Security.Cryptography.X509Certificates;
1595+
-using Microsoft.Extensions.Options;
1596+
-using Steeltoe.Common.Options;
1597+
+using Steeltoe.Common.Certificates;
1598+
-using Steeltoe.Security.Authentication.CloudFoundry;
1599+
+using Steeltoe.Security.Authorization.Certificate;
1600+
1601+
const string orgId = "a8fef16f-94c0-49e3-aa0b-ced7c3da6229";
1602+
const string spaceId = "122b942a-d7b9-4839-b26e-836654b9785f";
1603+
1604+
var builder = WebApplication.CreateBuilder(args);
1605+
1606+
-builder.Configuration.AddCloudFoundryContainerIdentity(orgId, spaceId);
1607+
+builder.Configuration.AddAppInstanceIdentityCertificate(new Guid(orgId), new Guid(spaceId));
1608+
-builder.Services.AddCloudFoundryContainerIdentity();
1609+
builder.Services
1610+
- .AddHttpClient<TestClient>((services, client) =>
1611+
- {
1612+
- client.BaseAddress = new Uri("https://localhost:7107");
1613+
- var options = services.GetRequiredService<IOptions<CertificateOptions>>();
1614+
- var b64 = Convert.ToBase64String(options.Value.Certificate.Export(X509ContentType.Cert));
1615+
- client.DefaultRequestHeaders.Add("X-Forwarded-Client-Cert", b64);
1616+
- });
1617+
+ .AddHttpClient<TestClient>(httpClient => httpClient.BaseAddress = new Uri("https://localhost:7107"))
1618+
+ .AddAppInstanceIdentityCertificate("X-Forwarded-Client-Cert");
1619+
1620+
var app = builder.Build();
1621+
1622+
var testClient = app.Services.GetRequiredService<TestClient>();
1623+
string orgResponse = await testClient.GetAsync("/test-same-org");
1624+
Console.WriteLine($"Org response: {orgResponse}");
1625+
string spaceResponse = await testClient.GetAsync("/test-same-space");
1626+
Console.WriteLine($"Space response: {spaceResponse}");
1627+
1628+
public class TestClient(HttpClient httpClient)
1629+
{
1630+
public async Task<string> GetAsync(string requestPath)
1631+
{
1632+
return await httpClient.GetStringAsync(requestPath);
1633+
}
1634+
}
1635+
```
1636+
1637+
> [!NOTE]
1638+
> Prior to Steeltoe 3.3.0, Steeltoe Certificate Auth used the header `X-Forwarded-Client-Cert`, which was not configurable.
1639+
> The code shown above is provided for compatibility between the versions. The preferred header name is `X-Client-Cert`.
1640+
> In Steeltoe 4.0, the default header is `X-Client-Cert`, so the parameter can be omitted if cross-compatibility is not required.
12551641
12561642
### DataProtection Key Store using Redis/Valkey
12571643

0 commit comments

Comments
 (0)