1

I have two apps, one that authenticate some user and generate a jwt if the user is valid, and save this jwt on the header with the name custom, as you can see:

    var jwt = require('jsonwebtoken')
    var bodyParser = require('body-parser')

    app.use(bodyParser.urlencoded({extended: false}))
    app.use(bodyParser.json({limit:'10mb'}))

    app.post('/login', (req, res) => {

    let usuarios = [
    {
        username: "Hannibal",
        password: "pass1"
    },
    {
        username: "Arnold",
        password: "pass2"
    }
];

let credentials = req.body.credentials;

let isValid = usuarios.some((validUser) => {
    return validUser.username == credentials.username && validUser.password == credentials.password;
});

if (isValid){
var tokenData = {
  username: credentials.username
}

var token = jwt.sign(tokenData, 'Secret Password', {
  expiresIn: 60 * 60 * 24 // expires in 24 hours
})

res.setHeader("custom", token)

}

    res.json(
{
    "response": {
        "status": isValid
    }
});  
})

The other validate the jwt.

    var jwt = require('jsonwebtoken')
    const express = require('express')
    const app = express()

    app.get('/secure', (req, res) => {
    var token = req.headers['custom']
    if(!token){
      res.status(401).send({
      error: "Es necesario el token de autenticación"
      })
       return
     }

   jwt.verify(token, 'Secret Password', function(err, user) {
     if (err) {
    res.status(401).send({
      error: 'Token inválido'
    })
  } else {
    res.send({
      message: 'Login exitoso!'
    })
  }
})
})

It's possible to do a mediator that call the validator and this one get the custom header and validate it? i try with this two but when i try with soap ui i keep getting a 401 (missing the custom token), until i declare the custom head.

<?xml version="1.0" encoding="UTF-8"?>
  <sequence name="Mediator" trace="disable" 
    xmlns="http://ws.apache.org/ns/synapse">
    <call blocking="true" description="">
      <endpoint>
        <http method="get" uri-template="http://localhost:3001/secure"/>
      </endpoint>
    </call>
   </sequence>

<sequence name="passJWT" xmlns="http://ws.apache.org/ns/synapse">
<property expression="$trp:custom" name="custom" scope="transport" type="STRING"/>
<header expression="get-property('custom')" name="custom" scope="transport"/>

Thanks in advance for any guide or tip!

  • Do you have it working and are just looking for advice on improving it, or are you looking for advice on how to get it working? – Riverchimp Jun 07 '18 at 03:13
  • hello, thx for the answer/question. I need an advice to make it work. I get the jwt generate from the post and save it under the name custom on the header, i just need that that header travel on the get, or put, etc... – Patricio Mora Jun 07 '18 at 03:41

1 Answers1

0

You should not need to touch your custom token in the meditaion sequence, when you send the message to your backend login service the custom header will get passed on.

A useful tool to help debug http headers to enable the http wire logs in conf/log4j.properties file. This will log the entire http payload to the logs so you can see the headers it is sending and receiving.

log4j.logger.org.apache.synapse.transport.http.wire=DEBUG

For an example I created this API with the middleman service that you are trying to create and a mock service for your backend token authentication.

<api context="/secureapi" name="LoginAPI" xmlns="http://ws.apache.org/ns/synapse">

    <!-- The Middleman API that your client app will talk to -->
    <resource methods="GET" protocol="http" url-mapping="/secure">
        <inSequence>
            <log level="custom">
                <property name="Secure service" expression="$trp:custom"/>
            </log>
            <property name="REST_URL_POSTFIX" action="remove" scope="axis2"/>
            <send>
                <endpoint>
                    <address uri="http://localhost:8280/secureapi/backend" format="rest"/>
                </endpoint>
            </send>
        </inSequence>
        <outSequence>
            <send/>
        </outSequence>
        <faultSequence/>
    </resource>


    <!-- This is a mock of you backend login service -->
    <resource methods="GET" protocol="http" url-mapping="/backend">
        <inSequence>
            <log level="custom">
                <property name="Backend" expression="$trp:custom"/>
            </log>
            <payloadFactory media-type="json">
                <format>
                    { message: 'Login exitoso!' }
                </format>
                <args/>
            </payloadFactory>
            <loopback/>
        </inSequence>
        <outSequence>
            <send/>
        </outSequence>
        <faultSequence/>
    </resource>
</api>

Removing the REST_URL_POSTFIX property is very important.

<property name="REST_URL_POSTFIX" action="remove" scope="axis2"/>

If i did not do this then the next time I try and send the message it will append /secure onto the end of it (so it will call http://localhost:8280/secureapi/backend/secure) which will result in a 404.

When I send a request to this API with the custom header set (I set the value to "jwtTokenString") the wso2carbon logs contain the following (I cut it down a bit to remove noise that is not important).

This is the middleman API receiving the request

[2018-06-07 16:45:24,957] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "GET /secureapi/secure HTTP/1.1[\r][\n]"
[2018-06-07 16:45:24,957] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "Host: my.host.name:8280[\r][\n]"
[2018-06-07 16:45:24,957] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "Connection: keep-alive[\r][\n]"
[2018-06-07 16:45:24,957] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "Cache-Control: no-cache[\r][\n]"
[2018-06-07 16:45:24,957] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36[\r][\n]"
[2018-06-07 16:45:24,957] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "custom: jwtTokenString[\r][\n]"
[2018-06-07 16:45:24,958] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "Postman-Token: ee489d08-ceb7-0cbe-de07-1544bf129c11[\r][\n]"
[2018-06-07 16:45:24,958] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "Accept: */*[\r][\n]"
[2018-06-07 16:45:24,958] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "Accept-Encoding: gzip, deflate[\r][\n]"
[2018-06-07 16:45:24,958] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "Accept-Language: en-NZ,en;q=0.9,en-US;q=0.8[\r][\n]"
[2018-06-07 16:45:24,958] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-4 >> "[\r][\n]"

Then the Middle man API then logs the token

[2018-06-07 16:45:24,959] [EI-Core]  INFO - LogMediator Secure service = jwtTokenString

Next is the middle man API sending the message to the backend login service (note the direction of the angle brackets is different, >> = message in, << = message out)

[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "GET /secureapi/backend HTTP/1.1[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "Accept: */*[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "Cache-Control: no-cache[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "custom: jwtTokenString[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "Postman-Token: ee489d08-ceb7-0cbe-de07-1544bf129c11[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "Accept-Encoding: gzip, deflate[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "Accept-Language: en-NZ,en;q=0.9,en-US;q=0.8[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "Host: localhost:8280[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "Connection: Keep-Alive[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Sender I/O dispatcher-4 << "[\r][\n]"

You can see that the custom header is still there. And finally the backend service receiving the message with the custom header

[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "GET /secureapi/backend HTTP/1.1[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept: */*[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Cache-Control: no-cache[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "custom: jwtTokenString[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Postman-Token: ee489d08-ceb7-0cbe-de07-1544bf129c11[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept-Encoding: gzip, deflate[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Accept-Language: en-NZ,en;q=0.9,en-US;q=0.8[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Host: localhost:8280[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "Connection: Keep-Alive[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"
[2018-06-07 16:45:24,961] [EI-Core] DEBUG - wire HTTP-Listener I/O dispatcher-1 >> "[\r][\n]"
Riverchimp
  • 404
  • 5
  • 14
  • Thanks for your response, so you're are saying that i can set this custom header (with the jwt i generate) and with the sequence pass it to the backend (for validate) just making a sequence like the first one i show you, but adding : – Patricio Mora Jun 07 '18 at 14:42
  • That should work, just try it and see. It if is not, check the wire logs to see that the header is getting passed and the URL is correct. – Riverchimp Jun 07 '18 at 20:24
  • thx, but i don't why i'm not getting the response i want, i keep getting a 401, i think (probably i'm wrong i'm new on wso2, synapse world) the first app should generate the jwt, save it under custom name, pass it to the other request and the validation app should extract this custom header, process it and return the success message, all from the first post request (using the mediator call to the get/validator). – Patricio Mora Jun 07 '18 at 21:55
  • Can you check if you backend authentication service is receiving the token? I want to narrow down where the problem is. – Riverchimp Jun 07 '18 at 22:13
  • hi, thx again, well using the sequence doesn't work, i mean from the post to the get the head doesn't pass, but when i try it with two calls (without the sequence) it work. – Patricio Mora Jun 08 '18 at 13:52