0

私は現在、SSO と SLO を実装するために、passport-saml で WSO2-IS 5.4.1 を使用しています。シングル サインオンは正しく機能していますが、完全なシングル ログアウトを適切に構成できないようです。

正直なところ、いくつかのことで混乱しています

  1. ログアウトを開始した SP に WSO2IS がログアウト要求を送信するのはなぜですか? このアクションは SAML リクエストではキャプチャされませんが、以下に示す IdP ターミナル エラーに記載されています。
  2. samlStrategy.logout もローカル ログアウトを実行しますか、それとも単にリクエストを作成して WSO2IS にリダイレクトするだけですか? 私が確認したすべてのサンプル コードには、ログアウト コールバックに req.logout() が含まれていますが、/wso2app/logout/callback ポストで req.logout() を行う前に、req.isAuthenticated() を false として取得しています。

アプリは WSO2IS saml URL に正しくリダイレ​​クトされ、WSO2IS はアプリ構成のコールバックにポストバックします。WSO2IS もユーザーのログアウトに成功しましたが、不要な SLO 要求をノード アプリに送り返しているようです。IdP のノード SP 構成については、以下の画像リンクを参照してください。

WSO2IS のノード アプリ構成

saml DEBUG を使用して IdP ターミナルで生成される主なエラー:

[2018-05-01 10:44:47,135] DEBUG {org.wso2.carbon.identity.sso.saml.servlet.SAMLSSOProviderServlet} - Query string : slo=true&SAMLRequest=nVFLS8QwEP4rJfdtm272NbRdF4pQWD2oePAioc26hTRTM1P15xu7KyyCHoS5ZOZ7ZSbffvQ2ejOeOnSFkHEqtmVOurcD7PEFR74zr6MhjgLOEUyTQozeAWrqCJzuDQE3cL%2B72UMWpzB4ZGzQigvK3wxNZDyHACKqq0I8b5aLTaN0dlCtXmmZzlu1FtHjd8hACUCi0dSOWDsOrVSuZ%2BlilsoHqUCFWsUyWz6JqArZO6d5Yh6ZB4Iksdhoe0Ri2Cg1T74SEuGWLBbsRyNOG4DJw%2F%2FjG%2BU7YaaHIU8udM6it4FXV9E1% 2Bl7z74IyllOna2eHCQqm153dta03RKIcg5e86sICZNxgf3Y6iZen148Llp8%3D [2018-05-01 10:44:47,140] DEBUG {org.wso2.carbon.identity.sso.saml.builders.SignKeyDataHolder} - システム キー ストアを使用したスーパーのキー データの初期化 [2018-tenant1 10:44:47,163] DEBUG {org.wso2.carbon.identity.sso.saml.servlet.SAMLSSOProviderServlet} - クエリ文字列: slo=true&SAMLRequest=nVFLS8QwEP4rJfdtm272NbRdF4pQWD2oePAioc26hTRTM1P15xu7KyyCHoS5ZOZ7ZSbffvQ2ejOeOnSFkHEqtmVOurcD7PEFR74zr6MhjgLOEUyTQozeAWrqCJzuDQE3cL%2B72UMWpzB4ZGzQigvK3wxNZDyHACKqq0I8b5aLTaN0dlCtXmmZzlu1FtHjd8hACUCi0dSOWDsOrVSuZ%2BlilsoHqUCFWsUyWz6JqArZO6d5Yh6ZB4Iksdhoe0Ri2Cg1T74SEuGWLBbsRyNOG4DJw%2F%2FjG%2BU7YaaHIU8udM6it4FXV9E1%2Bl7z74IyllOna2eHCQqm153dta03RKIcg5e86sICZNxgf3Y6iZen148Llp8%3D [2018-05-01 10:44:47,169] DEBUG {org.wso2.carbon.identity.sso.saml.logout.LogoutRequestSender} - A logoutReqSenderTaskスレッド プールに割り当てられています [2018-05-01 10:44:47,169] DEBUG {org.wso2.carbon.identity.sso.saml.session.SSOSessionPersistenceManager} - セッション インデックス 6ffb8168-3022 のセッション ID からセッション インデックスを取得しました- 4d77-9ecc-3bc168d6c5da [2018-05-01 10:44:47,345] デバッグ {org.wso2.carbon.identity.sso.saml.logout.LogoutRequestSender} - シングル ログアウト リクエストが次の宛先に送信されます。 http://localhost:3000/wso2app/logout/callbackMoved Temporarily [2018-05-01 10:44:47,348] DEBUG {org.wso2.carbon.identity.sso.saml.util.SAMLSSOUtil} - リクエスト メッセージ ��u�����)ඈm�� で返されます ����,�}4��.qǬ��Z�� [致命的なエラー] :1:1: プロローグではコンテンツを使用できません。[2018-05-01 10:44:47,368] エラー {org.wso2.carbon.identity.sso.saml.util.SAMLSSOUtil} - エンコードされた文字列 org.xml.sax.SAXParseException から AuthRequest を構築する際のエラー: コンテンツがありませんプロローグで許可されています。org.apache.xerces.parsers.DOMParser.parse(不明なソース) org.apache.xerces.jaxp.DocumentBuilderImpl.parse(不明なソース) javax.xml.parsers.DocumentBuilder.parse(不明なソース) org.wso2 org.wso2.carbon.identity.sso.saml.logout.LogoutRequestSender$LogoutReqSenderTask. http://localhost:3000/wso2app/logout/callback run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) 原因: org.xml.sax.SAXParseException: コンテンツはプロローグで許可されていません。org.apache.xerces.parsers.DOMParser.parse(不明なソース) org.apache.xerces.jaxp.DocumentBuilderImpl.parse(不明なソース) javax.xml.parsers.DocumentBuilder.parse(不明なソース) org.wso2 .carbon.identity.sso.saml.util.SAMLSSOUtil.unmarshall(SAMLSSOUtil.java:298) ... 7 もっと見る

ノードアプリ。user1 は IdP によって認証されるとすぐに /wso2app/logout にリダイレクトされることに注意してください。これはテスト用です。

const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const passport = require('passport');
const SamlStrategy = require('passport-saml').Strategy;
const fs = require('fs');

const app = express();

// logger middleware
function logger(req,res,next){
    console.log(req.method, req.url);
    next();
}
app.use(logger);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));

// express Session
app.use(session({
    secret: 'secret',
    saveUninitialized: true,
    resave: true
}));
app.use(passport.initialize());
app.use(passport.session());

// passport middleware
passport.serializeUser(function(user, done) {
    done(null, user);
});

passport.deserializeUser(function(user, done) {
    done(null, user);
});

const samlStrategy = new SamlStrategy({
    issuer: 'wso2app',

    // login endpoints
    entryPoint: 'https://localhost:9443/samlsso',   
    callbackUrl: 'http://localhost:3000/wso2app/login/callback',

    // logout endpoints
    logoutUrl: 'https://localhost:9443/samlsso?slo=true',
    logoutCallbackUrl: 'http://localhost:3000/success', 
    },
    function(profile, done){        

        return done(null,{      

            // subject claim, SAML:1.1 dialect  
            Email: profile.nameID,

            // requested claims, WSO2 internal dialect
            FirstName: profile['http://wso2.org/claims/givenname'], 
            LastName: profile['http://wso2.org/claims/lastname'],           
            Organization: profile['http://wso2.org/claims/organization'],
            Role: profile['http://wso2.org/claims/role'],

            // slo attributes
            nameID: profile.nameID,
            nameIDFormat: profile.nameIDFormat          
        });
    }); 
passport.use(samlStrategy);


app.get('/wso2app/login',   
    passport.authenticate('saml', {
        successRedirect: '/wso2app',
        failureRedirect: '/wso2app/login'       
    })
);  

app.post('/wso2app/login/callback', passport.authenticate('saml', { 
    failureRedirect: '/wso2app/login',
    failureFlash: true, 
    }),
    function(req, res){
        res.redirect('/wso2app')        
    }
);

app.get('/wso2app', function(req, res) {

    if (!req.isAuthenticated()) {       
        res.redirect('/wso2app/login');     
    }

    //parse domain from the user's email attribute in SAML response
    const domain = req.user.Email.substring(req.user.Email.lastIndexOf("@") + 1);
    console.log(domain);https://localhost:9443/samlsso?slo=true

    //use domain as index router, send specific users to their respective url
    switch(domain){
        case 'inst1.com':
            console.log(JSON.stringify(req.user));
            //res.redirect('/wso2app/inst1/');
            res.redirect('/wso2app/logout');
            break;
        case 'unv2.edu':
            console.log(JSON.stringify(req.user));
            res.redirect('/wso2app/unv2/');
            break;
        case 'inst3.com':
            console.log(JSON.stringify(req.user));
            res.redirect('/wso2app/inst3/');
            break;
        default:
            res.send("You're Authenticated but Unaffiliated, Your Credentials: " + JSON.stringify(req.user));
    }       
});

app.get('/wso2app/logout', function(req, res){

    console.log("req.user.nameID: " + req.user.nameID);
    console.log("req.user.nameIDFormat: " + req.user.nameIDFormat); 
    if (req.isAuthenticated()) {
        console.log("Still Auth in Node 1");        
    }

    samlStrategy.logout(req, function(err, request){
        if (!err) {
            res.redirect(request);
            console.log('request: ' + request);
        }       
    }); 
});

app.post('/wso2app/logout/callback', function(req,res){ 
    if (!req.isAuthenticated()) {       
        console.log("Already logged out");
    }
    req.logout();   
    res.redirect('http://localhost:3000/success');
});

app.listen(3000, function(){
    console.log('Server Started on Port 3000');
});

SLO リクエスト注: これは、ノード アプリから IdP に送信される適切な SLO リクエストであり、SAML ブラウザ ツールによってキャプチャされます。IdP からアプリに送り返された謎の slo リクエストは、IdP ターミナル エラーにのみ記載されています。

複数の投稿を確認しましたが、私の問題に関連する投稿が見つかりません。http://localhost:3000/wso2app/logout/callbackに送信されるログアウト リクエストの不可解な性質が懸念されますが、これが送信される理由がわかりません。これは、ここに示されている公式の SLO フローに従っていないようです。「[致命的なエラー] :1:1: コンテンツはプロローグでは許可されていません。過剰な空白文字に関連していますが、このリクエストがどのように、またはなぜ生成されているのかわかりません。どんな助けでも大歓迎です。

4

0 に答える 0