SAP-BTP-Spielwiese/app1/node_modules/@sap/xssec/doc/TokenInfo.md
Markus Rettig 775ac7b58c completed step 3 from the tutorial
you must login with an BTP account in order to see the app
2024-02-08 16:13:36 +01:00

4.2 KiB

TokenInfo

Since version 3.0.4 we have the TokenInfo object in the xssec library. This is a wrapper around all the information the token contains.

Security Note

Do not simply rely on the information within the token! The webapplication normally receives the token with the HTTP Request from "outside" the application. So there is a deep parameter validation needed!

Also if the token is signed, it may also contain dangerous information.

How to get the TokenInfo object

There are several ways to get the TokenInfo. If an error occurs NO security context is created. But the TokenInfo object is available, so you can do some logging.

If you create the SecurityContext on your own

xssec.createSecurityContext(access_token, config, function(error, securityContext, tokenInfo) {
    if (error) {
        console.log('tokenInfo is also available if you have an error', tokenInfo.getPayload())
        return;
    }
    console.log('Security Context created successfully', tokenInfo.getPayload());
    console.log('You can also retrieve it from the SecurityContext', securityContext.getTokenInfo());
});

If you use the passport library.

The tokenInfo object is attached to the request object in the JWTStrategy middleware. (more here) Only if the middleware could not find a bearer token in the HTTP header, there is no tokenInfo object created.

The documentation for a default error handler in express you find here

passport.use(new JWTStrategy(config));

app.use(passport.initialize());

//don't forget to set failWithError to true.
//Otherwise the errorHandler will not be called
app.use(passport.authenticate('JWT', { session: false, failWithError: true })); 

// simple express Error Handler
app.use(function(err, req, res, next) {
  //be aware that the error handler is not only for the passport errors!
  var tokenInfo = req.tokenInfo;
  if(tokenInfo) {
    //err is exception thrown but not the error of the tokenValidation
    //to get the errorObject from xsuaa
    var xserror = tokenInfo.getErrorObject()  
    
    //to the logging
    console.error(xserr, tokenInfo.getPayload());
  }
  
  res.status(err.status);
  res.send(err.message);
});

API Description

TokenInfo(encoded_token)

Code says more than words :-)

var tokenInfo = new TokenInfo(encodedTokenAsString);

///// Get the Token-information as a whole
var payload = tokenInfo.getPayload(); //Get the token payload
var header = tokenInfo.getHeader();   //Get the token header
var encoded = tokenInfo.getTokenValue(); //returns the encoded token string

var exp = tokenInfo.getExpirationDate(); //returns a Date object or null if not available
var iat = tokenInfo.getIssuedAt(); //returns a Date object or null if not available
var iss = tokenInfo.getIssuer(); //returns a string or null if not available

var is_xsuaa = tokenInfo.isTokenIssuedByXSUAA(); //returns true, if the token is a XSUAA token

///// Error Handling
tokenInfo.isDecoded(); //returns true, if a token could be decoded
tokenInfo.isValid();    //returns true, if no error object is attached

tokenInfo.getErrorObject(); //return the error object if there is one


///// Verification of an encoded token

//you can pass a key Callback to retrieve the key asyncronously
function getKeyCB(header, callback) {
  client.getSigningKey(header.kid, function(err, key) {
    var signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}

tokenInfo.verify(getKeyCB, function(err, tokenInfo) {
    if(err) {
        console.error(err.errorCode, err.message);
        console.error(err.stack);

        //tokenInfo is also available, if there was a verification error.
        console.log(tokenInfo.getPayload());
    } else {
        //yeah, it was verified
        ...
    }
});

//instead of a callback you can directly give the verification key to the function
tokenInfo.verify("123456", function(err, tokenInfo) {
    ...
});

Future Plans

We have plans to provide some more functionality here in the future:

  • provide not only verify, but also sign functionality
  • easy create tokens for unittesting