eXist-db / existdb-saml

XQuery module that implements SAML v2 single sign-on
GNU Lesser General Public License v2.1
4 stars 3 forks source link

HTTP Error 500 while integrating SAML[BUG] #3

Closed upendart closed 3 years ago

upendart commented 3 years ago

I uploaded the SAML and configured the controller.xql as mentioned in the Plugin on the application. When I tried to run the URL: http://localhost:8080/ and http://localhost:8080/SAML2SP, I am getting below errors.

URL: http://localhost:8080/ Error: HTTP ERROR 500 javax.servlet.ServletException: javax.servlet.ServletException: An error occurred while processing request to /exist/: exerr:ERROR Authentication failed [at line 145, column 9] In function: exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm]

URI: | /exist/

500 javax.servlet.ServletException: javax.servlet.ServletException: An error occurred while processing request to /exist/: exerr:ERROR Authentication failed [at line 145, column 9] In function: exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm] XQueryURLRewrite javax.servlet.ServletException: javax.servlet.ServletException: An error occurred while processing request to /exist/: exerr:ERROR Authentication failed [at line 145, column 9] In function: exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm] javax.servlet.ServletException: An error occurred while processing request to /exist/: exerr:ERROR Authentication failed [at line 145, column 9] In function: exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm] org.exist.xquery.XPathException: exerr:ERROR Authentication failed [at line 145, column 9] In function: exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm] exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm] org.exist.security.AuthenticationException: Wrong password for user [exsaml]

Caused by:

javax.servlet.ServletException: javax.servlet.ServletException: An error occurred while processing request to /exist/: exerr:ERROR Authentication failed [at line 145, column 9]
In function:
    exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm]
    exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm]
    exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm]
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:162)
    at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:767)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:500)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.servlet.ServletException: An error occurred while processing request to /exist/: exerr:ERROR Authentication failed [at line 145, column 9]
In function:
    exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm]
    exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm]
    exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm]
    at org.exist.http.urlrewrite.XQueryURLRewrite.service(XQueryURLRewrite.java:370)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder$NotAsyncServlet.service(ServletHolder.java:1386)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:755)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617)
    at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1607)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1297)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1577)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1212)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:221)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
    ... 18 more
Caused by: org.exist.xquery.XPathException: exerr:ERROR Authentication failed [at line 145, column 9]
In function:
    exsaml:store-authnreqid(xs:string, xs:string) [114:19:/db/apps/existdb-saml/content/exsaml.xqm]
    exsaml:build-saml-authnreq() [92:17:/db/apps/existdb-saml/content/exsaml.xqm]
    exsaml:build-authnreq-redir-url(xs:string) [35:29:/db/apps/existdb-saml/content/exsaml.xqm]
    at org.exist.xquery.functions.system.AsUser.eval(AsUser.java:85)
    at org.exist.xquery.InternalFunctionCall.eval(InternalFunctionCall.java:41)
    at org.exist.xquery.DebuggableExpression.eval(DebuggableExpression.java:58)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:111)
    at org.exist.xquery.UserDefinedFunction.eval(UserDefinedFunction.java:162)
    at org.exist.xquery.FunctionCall.evalFunction(FunctionCall.java:305)
    at org.exist.xquery.FunctionCall.eval(FunctionCall.java:223)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:99)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:111)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:111)
    at org.exist.xquery.UserDefinedFunction.eval(UserDefinedFunction.java:162)
    at org.exist.xquery.FunctionCall.evalFunction(FunctionCall.java:305)
    at org.exist.xquery.FunctionCall.eval(FunctionCall.java:223)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:99)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:111)
    at org.exist.xquery.UserDefinedFunction.eval(UserDefinedFunction.java:162)
    at org.exist.xquery.FunctionCall.evalFunction(FunctionCall.java:305)
    at org.exist.xquery.FunctionCall.eval(FunctionCall.java:223)
    at org.exist.xquery.AbstractExpression.eval(AbstractExpression.java:71)
    at org.exist.xquery.PathExpr.eval(PathExpr.java:280)
    at org.exist.xquery.AttributeConstructor.eval(AttributeConstructor.java:93)
    at org.exist.xquery.ElementConstructor.eval(ElementConstructor.java:224)
    at org.exist.xquery.AbstractExpression.eval(AbstractExpression.java:71)
    at org.exist.xquery.PathExpr.eval(PathExpr.java:280)
    at org.exist.xquery.ElementConstructor.eval(ElementConstructor.java:330)
    at org.exist.xquery.DebuggableExpression.eval(DebuggableExpression.java:58)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:111)
    at org.exist.xquery.LetExpr.eval(LetExpr.java:111)
    at org.exist.xquery.ConditionalExpression.eval(ConditionalExpression.java:100)
    at org.exist.xquery.AbstractExpression.eval(AbstractExpression.java:71)
    at org.exist.xquery.PathExpr.eval(PathExpr.java:280)
    at org.exist.xquery.AbstractExpression.eval(AbstractExpression.java:71)
    at org.exist.xquery.XQuery.execute(XQuery.java:261)
    at org.exist.xquery.XQuery.execute(XQuery.java:185)
    at org.exist.http.urlrewrite.XQueryURLRewrite.runQuery(XQueryURLRewrite.java:677)
    at org.exist.http.urlrewrite.XQueryURLRewrite.service(XQueryURLRewrite.java:243)
    ... 40 more
Caused by: org.exist.security.AuthenticationException: Wrong password for user [exsaml] 
    at org.exist.security.internal.RealmImpl.authenticate(RealmImpl.java:284)
    at org.exist.security.internal.SecurityManagerImpl.authenticate(SecurityManagerImpl.java:404)
    at org.exist.xquery.functions.system.AsUser.eval(AsUser.java:83)
    ... 75 more
URL: http://localhost:8080/SAML2SP ![image](https://user-images.githubusercontent.com/23036620/123331608-7dfdac80-d50d-11eb-8284-dc074b74fef6.png) Can anyone let me know what the issues and how to fix them? Thank you, Upendar
chakl commented 3 years ago

org.exist.security.AuthenticationException: Wrong password for user [exsaml]

The exsaml code tries to execute a function as DB user exsaml but that failed because of password mismatch. Please assign the password specified in file config-exsaml.xml in tag exsaml-creds/@pass to the DB user exsaml.

In EXide, you could do this by executing sm:passwd('exsaml', 'THE PASSWORD YOU CONFIGURED').

Please report back whether that fixes the issue.

Also, check spelling of the URIs: http://localhost:8080/SAML2SP != http://localhost:8080/SAML2sp (lowercase "sp"), that may also lead to errors.

Looks like the documentation is lacking the required info to set the "exsaml" user password. That's a bug. And we did not notice because we set DB user passwords anyway using Ansible. Thanks for reporting.

upendart commented 3 years ago

The org.exist.security.AuthenticationException: Wrong password for user [exsaml] is fixed and able to redirect to IDP endpoint.

But the URL: http://localhost:8080/SAML2SP still has the same issue "HTTP ERROR 404 Not Found" image

Can you take a look?

Thanks, Upendar

chakl commented 3 years ago

Edited: Can you please post the first lines of your config-exsaml.xml file up to and including the <idp> tag? Note you should not include the <crypto> tag as the hmac-key attribute contains confidential information. Same for <exsaml-creds ... pass="...">.

This is most likely the problem:

Also, did you follow the README.md file, section "Edit controller.xql of Your Application"? In particular, do you have the code snippet starting with else if($exist:path = "/SAML2SP") in your controller.xql?

The /SAML2SP endpoint in your controller.xql is either missing or does not get executed. The controller.xql must handle the /SAML2SP endpoint, including the call to exsaml:process-saml-response-post(), SAML result checking, and redirection to the SAML relaystate, as described in the README file.

If you do have code like that in controller.xql, you may need to debug whether that particular code branch gets executed at all.

upendart commented 3 years ago

I updated the controller.xql file as mentioned in README.md. Please see the updated etc\webapp\controller.xql.


(: This is the main controller for the web application. It is called from the XQueryURLRewrite filter configured in web.xml. :) xquery version "3.0";

(:~ ------------------------------------------------------- Main controller: handles all requests not matched by sub-controllers. ------------------------------------------------------- :)

declare namespace c="http://exist-db.org/xquery/controller"; declare namespace expath="http://expath.org/ns/pkg";

import module namespace request="http://exist-db.org/xquery/request"; import module namespace xdb = "http://exist-db.org/xquery/xmldb"; import module namespace exsaml="http://exist-db.org/xquery/exsaml" at 'xmldb:///db/apps/existdb-saml/content/exsaml.xqm';

declare function local:get-dashboard() { let $path := collection(repo:get-root())//expath:package[@name = "http://exist-db.org/apps/dashboard"] return if ($path) then substring-after(util:collection-name($path), repo:get-root()) else () }; declare option exist:serialize "method=html media-type=text/html indent=no";

if (exsaml:is-enabled() and not(exsaml:check-valid-saml-token())) then ( let $debug := exsaml:log('info', "controller: no valid token, redirect to SAML auth") let $return-path := "/exist/apps" || $exist:controller || $exist:path return

)

(: if logout, invalidate SAML token :) else if ($exist:path = '/logout') then ( if (exsaml:is-enabled()) then exsaml:invalidate-saml-token() else () ,

...
)

(: handle SP endpoint to process SAML response in HTTP POST :) else if($exist:path = "/SAML2SP") then ( let $log := util:log('info', "SAML2SP: processing SAML response") let $status := exsaml:process-saml-response-post() let $log := util:log('debug', "endpoint SAML2SP; status: " || $status/@code) return if ($status/@code >= 0) then (: forward to page that was requested by the user :) let $debug := util:log("info", "Auth success - code " || $status/@code || " - relaystate: " || $status/@relaystate) return

    else
        (: if SAML failed, display an error message for now :)
        <data>{string($status/@msg) || ": " || string($status/@data)}</data>

)

else ( let $query := request:get-parameter("q", ()) return (: redirect webapp root to index.xml :) if ($exist:path eq '') then

else if ($exist:path eq '/') then
    let $dashboard := local:get-dashboard()
    return
        <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
        {
        if ($dashboard) then
            if(request:get-uri() = "/exist/" and request:get-header("X-Forwarded-URI") = "/") then
               <redirect url="/apps/{$dashboard}/"/>
            else
               <redirect url="apps/{$dashboard}/"/>
        else
            <redirect url="404.html"/>
        }
        </dispatch>
else
    <ignore xmlns="http://exist.sourceforge.net/NS/exist">
        <cache-control cache="yes"/>
    </ignore>

)


When I tried to debug, I am getting the below error "Error running 'controller.xql ': No data source found for name: null" image

FYI, Please the below config-exsaml.xml configurations used for testing

Thanks, Upendar
chakl commented 3 years ago

Your config looks ok. The controller code you posted is badly formatted (<stuff in angle brackets missing>), so it's hard to tell. Looks like an issue in the controller failed SAML authentication to me.

Check logfile $EXIST_HOME/logs/exist.log for log messages containing "exsaml:. You should see something like SAML2SP: processing SAML response, that means the SAML answer from the IDP has reached your local /SAML2SP endpoint. If SAML authentication was successful, you should see Auth success - code ... - relaystate .... If you see the first but not the second message, it likely means SAML authentication failed. You may find further details in the log. You may also want to change the log level in controller.xql line util:log('debug', "endpoint SAML2SP; status: " || $status/@code) from debug to info to see the result status of SAML authentication.

chakl commented 3 years ago

Closing this issue. This is not a bug.

Suboptimal documentation triggered user deployment errors. Has been fixed by enhancing README.md, will get further improved by some "debugging guide" documentation.

Upendar, thanks for your input! Please open a new issue if you hit problems when dealing with SAML responses from your IDP.