@sap/xssec
Advanced tools
Comparing version 3.2.1 to 3.2.2
# Change Log | ||
All notable changes to this project will be documented in this file. | ||
## 3.2.2 - 2020-06-16 | ||
- Support for tokenexchanges with X.509 certificates managed by XSUAA | ||
- Support for tokenexchanges with manually managed X.509 certificates | ||
- support for configuration objects that does not provide a clientsecret (but a certificate) | ||
## 3.2.1 - 2020-06-01 | ||
@@ -5,0 +10,0 @@ - Add some more error and tracing information |
@@ -63,4 +63,5 @@ 'use strict'; | ||
} | ||
if (!serviceCredentials.clientid || !serviceCredentials.clientsecret) { | ||
return new Error('Invalid service credentials: Missing clientid/clientsecret.'); | ||
if (!serviceCredentials.clientid) { | ||
//client_secret will be checked later (only if really needed) | ||
return new Error('Invalid service credentials: Missing clientid.'); | ||
} | ||
@@ -92,2 +93,6 @@ if (!serviceCredentials.url) { | ||
if(serviceCredentials.certificate) { | ||
urlWithCorrectSubdomain = serviceCredentials.certurl; | ||
} | ||
return urlWithCorrectSubdomain; | ||
@@ -126,4 +131,3 @@ } | ||
response_type: 'token', | ||
client_id: serviceCredentials.clientid, | ||
client_secret: serviceCredentials.clientsecret | ||
client_id: serviceCredentials.clientid | ||
}, | ||
@@ -133,2 +137,14 @@ timeout: timeout | ||
if(serviceCredentials.certificate) { | ||
options.key = serviceCredentials.key; | ||
options.cert = serviceCredentials.certificate; | ||
} else { | ||
//make sure we have a client_secret set here | ||
if (!serviceCredentials.clientsecret) { | ||
throw new Error('Invalid config: Missing clientsecret.'); | ||
} | ||
options.form.client_secret = serviceCredentials.clientsecret; | ||
} | ||
appendAdditonalAttribites(options, additionalAttributes); | ||
@@ -178,23 +194,30 @@ | ||
if(error) { | ||
error.statuscode = 500; | ||
return cb(error, null); | ||
} | ||
var urlWithCorrectSubdomain = buildSubdomain(serviceCredentials, subdomain); | ||
const urlWithCorrectSubdomain = buildSubdomain(serviceCredentials, subdomain); | ||
// jwt bearer flow | ||
var options = buildOptions(serviceCredentials, | ||
additionalAttributes, | ||
urlWithCorrectSubdomain, | ||
'urn:ietf:params:oauth:grant-type:jwt-bearer', | ||
zoneId, | ||
10*1000); | ||
try { | ||
// jwt bearer flow | ||
var options = buildOptions(serviceCredentials, | ||
additionalAttributes, | ||
urlWithCorrectSubdomain, | ||
'urn:ietf:params:oauth:grant-type:jwt-bearer', | ||
zoneId, | ||
10*1000); | ||
//add Assertion | ||
options.form.assertion = appToken; | ||
//add Assertion | ||
options.form.assertion = appToken; | ||
if (scopes !== null) { | ||
options.form.scope = scopes; | ||
if (scopes !== null) { | ||
options.form.scope = scopes; | ||
} | ||
return _requestToNetwork("requestUserToken", options, getTokenResponseHandler(cb)); | ||
} catch(e) { | ||
//the verification of the serviceCredentials fails | ||
e.statuscode = 500; | ||
return cb(e); | ||
} | ||
return _requestToNetwork("requestUserToken", options, getTokenResponseHandler(cb)); | ||
} | ||
@@ -210,4 +233,5 @@ | ||
// input validation | ||
var error = validateParameters(serviceCredentials, cb); | ||
const error = validateParameters(serviceCredentials, cb); | ||
if(error) { | ||
error.statuscode = 500; | ||
return cb(error, null); | ||
@@ -217,14 +241,19 @@ } | ||
// adapt subdomain in service url, if necessary | ||
var urlWithCorrectSubdomain = buildSubdomain(serviceCredentials, subdomain); | ||
const urlWithCorrectSubdomain = buildSubdomain(serviceCredentials, subdomain); | ||
var options = buildOptions(serviceCredentials, | ||
additionalAttributes, | ||
urlWithCorrectSubdomain, | ||
'client_credentials', | ||
zoneId, | ||
2*1000); | ||
try { | ||
const options = buildOptions(serviceCredentials, | ||
additionalAttributes, | ||
urlWithCorrectSubdomain, | ||
'client_credentials', | ||
zoneId, | ||
2*1000); | ||
appendAdditonalAttribites(options, additionalAttributes); | ||
return _requestToNetwork("requestClientCredentialsToken", options, getTokenResponseHandler(cb)); | ||
appendAdditonalAttribites(options, additionalAttributes); | ||
return _requestToNetwork("requestClientCredentialsToken", options, getTokenResponseHandler(cb)); | ||
} catch(e) { | ||
//the verification of the serviceCredentials fails | ||
e.statuscode = 500; | ||
return cb(e); | ||
} | ||
}; | ||
@@ -231,0 +260,0 @@ |
@@ -37,5 +37,3 @@ 'use strict'; | ||
} | ||
if (!config.clientsecret) { | ||
return throw500('Invalid config: Missing clientsecret.'); | ||
} | ||
if (!config.url) { | ||
@@ -42,0 +40,0 @@ return throw500('Invalid config: Missing url.'); |
{ | ||
"name": "@sap/xssec", | ||
"version": "3.2.1", | ||
"version": "3.2.2", | ||
"description": "XS Advanced Container Security API for node.js", | ||
@@ -5,0 +5,0 @@ "main": "./lib", |
@@ -172,3 +172,3 @@ @sap/xssec: XS Advanced Container Security API for node.js | ||
``` | ||
### Support for automatic IAS to XSUAA token conversion | ||
### Support for automatic IAS to XSUAA token exchange | ||
Since verison 3.1.2 it is supported to automatically exchange an incoming IAS token with an XSUAA token, so the token contains scopes like XSUAA applications expect. | ||
@@ -243,2 +243,41 @@ | ||
### Support for X.509 authentication for token exchange | ||
XSUAA offers the possibility to use X.509 authentication. | ||
Since version 3.2.2 the node-xssec library supports to use this. | ||
As a developer you normally do not need to do something differently. You create a SecurityContext with the configuration object you get from the environment. | ||
If the XSUAA is configured to use X.509 the config object does not contain a `clientsecret`. Instead of this, there are a `certificate` and a `key` attributes. | ||
The library will use these attributes during token exchanges to fetch the tokens from xsuaa using mtls. | ||
#### X.509 with XSUAA managed certificates | ||
If your XSUAA instance is configured to manage certificates and keys on its own, you can take the configuration object from VCAP services and pass it to the `createSecurityContext` method. | ||
The needed `certificate` and `key` attributes are already filled. | ||
There is no difference to client-credential based token exchange. | ||
#### X.509 with external certificates | ||
If you configured your XSUAA instance to use an external managed certificate/key you need to provide the `key` attribute to the configuration object. | ||
For this you take the JSON from VCAP-Services and add the PEM encoded key as a string to the configuration. | ||
```js | ||
//read xsuaa config from VCAP | ||
const config = xsenv.getServices({xsuaa:{tag:'xsuaa'}}).xsuaa; | ||
const myExternalManagedKey = "-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----\n"; | ||
config.key = myExternalManagedKey; | ||
//if using passport | ||
passport.use(new JWTStrategy(config)); | ||
//or create a security context directly | ||
xssec.createSecurityContext(access_token, config, function(error, securityContext, tokenInfo) { | ||
//now you can run a tokenExchange with the provided key | ||
xssec.requestToken(config, constants.TYPE_USER_TOKEN, null, function(err, data) { | ||
}) | ||
}); | ||
``` | ||
### Usage in Docker | ||
@@ -257,4 +296,2 @@ | ||
However, there are some use cases, when a "foreign" token could be accepted although it was not intended for the current application. If you want to enable other applications calling your application backend directly, you can specify in your xs-security.json file an access control list (ACL) entry and declare which OAuth client from which Identity Zone may call your backend. | ||
Parameters: | ||
@@ -261,0 +298,0 @@ |
118233
1654
427