TencentWSRD / connect-cas2

NodeJS implement of CAS(Central Authentication Service) client.
MIT License
108 stars 44 forks source link

CAS SLO not working #10

Open soumyart opened 7 years ago

soumyart commented 7 years ago

Implemented the slo as per the doc but CAS Single Logout is not working as expected.

APP1: node app implemented connect-cas2 APP2: spring webapp implemented CAS java config

Both APP1 and APP2 used the same CAS.

When I logged out from APP1, APP2 also getting logged out. But when I logged out from APP2, APP1 is still accessible.

Below is my connect-cas2 configuration:

{
        servicePrefix:"http://localhost:8080",
        serverPath: "https://localhost:8443/cas",
        paths: {
            validate: '/app-client',
            serviceValidate: '/serviceValidate',
            proxy: '',
            login: '/login',
            logout: '/logout',
            proxyCallback: ''
        },
        redirect: false,
        gateway: false,
        renew: false,
        slo: true,
        fromAjax: {
            header: 'x-client-ajax',
            status: 418
        }
}
xiaoyuze88 commented 7 years ago

First of all, make sure you use CAS middleware before bodyParser.

If you want to enable slo(single sign logout) feature, you need to use casClient.core() middleware before bodyParser, because the SLO need to access a POST request's raw body from CAS server.

Second, when you logging out APP2, check out APP1's log to see whether this line has been logged: Receive slo request... Trying to logout. , if not, that means APP1 don't even receive the logout request from your CAS server.

Hope these will help :)

soumyart commented 7 years ago

I have used the casClient.core() middleware before body parser.

let casClient = new ConnectCas({
        servicePrefix: CASConfig.serviceUrl,
        serverPath: CASConfig.casUrl,
        paths: {
            validate: '/client',
            serviceValidate: '/serviceValidate',
            proxy: '',
            login: '/login',
            logout: '/logout',
            proxyCallback: ''
        },
        restletIntegration: null,
        slo: true,
        fromAjax: {
            header: 'x-client-ajax',
            status: 418
        }
    });

    app.use(casClient.core());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

    app.get('/logout', function (req, res, next) {
        casClient.logout()(req, res, next);
    });

I logged out from APP2 but didn't receive any SLO log in APP1.

xiaoyuze88 commented 7 years ago

In default, the SLO logout request should be a POST request to this path: /${paths.validate}, which body contains a raw XML, sent by your CAS server.

It might be different depending on your CAS server's setting, APP1 could only logout itself when it receive the logout request.

The XML in the SLO request's body should be something like this:

<samlp:SessionIndex>{YOUR CAS TICKET}</samlp:SessionIndex>
soumyart commented 7 years ago

Now I'm getting Receive slo request... Trying to logout. log but the SLO failed. When I debug the slo.js of connect-cas2 found that cas response is in url encode format.

logoutRequest=%3Csamlp%3ALogoutRequest+xmlns%3Asamlp%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aprotocol%22+ID%3D%22LR-3-5wEszCI1hgIUpIbwRSfFcHewn4vwvrfkzMP%22+Version%3D%222.0%22+IssueInstant%3D%222017-06-16T16%3A01%3A53Z%22%3E%3Csaml%3ANameID+xmlns%3Asaml%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aassertion%22%3E%40NOT_USED%40%3C%2Fsaml%3ANameID%3E%3Csamlp%3ASessionIndex%3EST-3-jy1Yk3ORWASgeAaeYmTg-machine1%3C%2Fsamlp%3ASessionIndex%3E%3C%2Fsamlp%3ALogoutRequest%3E

So I'm getting Slo request receive, but body content is not valid error, due to the if block in slo.js:31 if (!/<samlp:SessionIndex>(.*)<\/samlp:SessionIndex>/.exec(body))

yuyongyu08 commented 6 years ago

I solved this problem by this way, but I'm not sure it is standard or not. change if (!/<samlp:SessionIndex>(.*)<\/samlp:SessionIndex>/.exec(body)) to if (!/<samlp:SessionIndex>(.*)<\/samlp:SessionIndex>/.exec(decodeURIComponent(body)))

soumyart commented 6 years ago

@yuyongyu08 I have already created a PR long back.

@xiaoyuze88 can you review it, if it is the standard way to solve.

weixiaohuster commented 6 years ago

@soumyart i also didn't receive any SLO log in my app. what you did to make the log display? whether i put cas before bodyparser or after, it doesn't work.

weixiaohuster commented 6 years ago

I have received the slo log, just becase the network is not available from the cas server to my local network. I also modify the slo.js, and the slo works. @xiaoyuze88 can you merge @soumyart 's PR ?