on 2023 Feb 10 6:11 AM
Hi Experts,
we are currently developing an application based on CAP. Additionally we a have a legacy ASP.NET application that we want to reuse, because it would be too much work to rebuild in CAP.
Therefore, we want to deploy the application using the .NET Core buildpack on Cloud Foundry. For secure access we would bind an XSUAA instance to both the CAP application and the .NET application.
Do you have any experience in using an XSUAA instance together with a .NET Container to perform proper authorization and authentication?
Request clarification before answering.
Thanks all for the provided suggestions. I now got a working solution with a package from Microsoft and the standard procedure for securing ASP.NET Core application. I found a detailed video for Adding Jwt Authentication & Authorization in ASP.NET Core which was really helpful.
The only tricky part where I struggled a bit was the security key which is neccesary to validate the signature of the token.
The basic configuration how the token should be validated is done by configuring the JWT Bearer options:
public void Configure(JwtBearerOptions o) {
o.TokenValidationParameters = new TokenValidationParameters {
ValidIssuer = $"{_env.XsuaaCredentials.Url}/oauth/token",
ValidAudience = _env.XsuaaCredentials.ClientId,
ValidateAudience = true,
ValidateLifetime = true,
IssuerSigningKey = _keyManager.GetSecurityKey(),
ValidateIssuer = true,
ValidateIssuerSigningKey = true
};
}The logic for reading the security key is then:
public SecurityKey GetSecurityKey() {
if (_key == null) {
RSA rsa = RSA.Create();
rsa.ImportFromPem(_env.XsuaaCredentials.VerificationKey);
_key = new RsaSecurityKey(rsa);
}
return _key;
}The "VerificationKey" property is filled from VCAP_SERVICES.xsuaa[0].credentials.verificationkey.
To secure a service endpoint some authorization options have to be configured and mapped to a so called "Policy":
public void Configure(AuthorizationOptions options) {
options.AddPolicy(IIdentityData.DefaultAuthPolicyName, p => {
p.RequireClaim(AuthorizedPartyClaim, _env.XsuaaCredentials.ClientId!);
p.RequireClaim(ZoneIdClaim, _env.XsuaaCredentials.ZoneId!);
});
// add policy to check scopes defined in /xs-security.json
options.AddPolicy(IIdentityData.PolicyName1, p => {
p.RequireClaim(
ScopeClaim,
$"{_env.XsuaaCredentials.XsAppName}.{IIdentityData.ScopeValue1}"
);
});
options.AddPolicy(IIdentityData.PolicyName2, p => {
p.RequireClaim(
ScopeClaim,
$"{_env.XsuaaCredentials.XsAppName}.{IIdentityData.ScopeValue2}"
);
});
}After this is done, the actual endpoints in a resource controller can be configured
[HttpPost()]
[Authorize(Policy = IIdentityData.DefaultAuthPolicyName)]
[Authorize(Policy = IIdentityData.PolicyName1)]
public async Task<ActionResult<Result>> Post(Input input) {
// your code...
}It is similar to securing service endpoints in CAP, and also neatly doable via annotations.
If I have some spare time, I will write detailed a blog post about the whole setup.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
XSUAA is the same UAA service which is part of Cloud Foundry, with a few SAP-specific additions. It's just an OAuth2 server which you can connect to using the credentials read from the VCAP_SERVICES environment variable.
I suggest checking out the UAA documentation and source code (it's OSS):
https://github.com/cloudfoundry/uaa
And looking for OAuth2 client frameworks/middleware for .NET, like the ones listed here: https://oauth.net/code/dotnet
If you bind your Cloud Foundry application to an instance of the XSUAA service, you will see something like this in your VCAP_SERVICES:
{
...
"xsuaa": [
{
"label": "xsuaa",
"provider": null,
"plan": "application",
"name": "example-uaa",
"tags": [
"xsuaa"
],
"instance_guid": "deadbeef-035e-4e69-bdea-deadbeed",
"instance_name": "example-uaa",
"binding_guid": "deadbeef-035e-4e69-bdea-deadbeed",
"binding_name": null,
"credentials": {
"tenantmode": "dedicated",
"sburl": "https://internal-xsuaa.authentication.us10.hana.ondemand.com",
"subaccountid": "deadbeef-035e-4e69-bdea-deadbeed",
"credential-type": "instance-secret",
"clientid": "sb-my-demo-app!t12345",
"xsappname": "my-demo-app!t12345",
"clientsecret": "ab/AbcdAbcd+AbcdAbcdAbcd=",
"url": "https://vpdev.authentication.us10.hana.ondemand.com",
"uaadomain": "authentication.us10.hana.ondemand.com",
"verificationkey": "-----BEGIN PUBLIC KEY-----\n(...)\n-----END PUBLIC KEY-----",
"apiurl": "https://api.authentication.us10.hana.ondemand.com",
"identityzone": "example",
"identityzoneid": "deadbeef-035e-4e69-bdea-deadbeed",
"tenantid": "deadbeef-035e-4e69-bdea-deadbeed",
"zoneid": "deadbeef-035e-4e69-bdea-deadbeed"
},
"syslog_drain_url": null,
"volume_mounts": []
}
],
...
}
This variable is set in the process environment before your application starts, so at application start you can read/parse VCAP_SERVICES as JSON and provide the connection info/credentials to your OAuth2 library/framework.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Never used that combination myself nor have I spoken to anyone that has to be honest. How about running that asp.net app on Azure App Service and connecting from BTP/CAP via SAP Private Link? That way the playing field might be more straight forward.
KR
Martin
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
HI Martin,
thank you for your reply. That would be our last resort if we can't get it to work in CF. The deployment to CF would allow us to have only one artifact (MTAR) for deployment. What do you think about Jwt.Net, a JWT (JSON Web Token) implementation for .NET?
CU
Gregor
| User | Count |
|---|---|
| 17 | |
| 8 | |
| 7 | |
| 6 | |
| 4 | |
| 3 | |
| 3 | |
| 2 | |
| 2 | |
| 2 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.