[ 
https://issues.apache.org/jira/browse/NIFI-7771?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17234160#comment-17234160
 ] 

M Tien commented on NIFI-7771:
------------------------------

[~humpfhumpf] - I was able to reproduce the issue and tested your PR. I've 
confirmed that your changes were able to fix the looping issue, remove the JWT, 
and issue a new JWT. I left a +1 comment on the PR. Thanks!

> Infinite loop on WebUI when node stopped in cluster
> ---------------------------------------------------
>
>                 Key: NIFI-7771
>                 URL: https://issues.apache.org/jira/browse/NIFI-7771
>             Project: Apache NiFi
>          Issue Type: Bug
>          Components: Core UI
>    Affects Versions: 1.10.0, 1.9.2, 1.12.0, 1.11.4
>         Environment: Linux
>            Reporter: humpfhumpf
>            Assignee: M Tien
>            Priority: Critical
>          Time Spent: 20m
>  Remaining Estimate: 0h
>
> h2. Context
> Before the bug occurs, one needs:
>  * a load-balancer which uses client IP affinity to “select” one NiFi 
> instance in the cluster;
>  * a fresh and successful OpenID Connect authentication on WebUI.
> Then, stops the NiFi instance, which was “selected” by the load-balancer for 
> you.
> In the mean time, the WebUI (javascript) continues to poll WebAPI by fetching 
> status URLs, but all calls return HTTP 401 error. Then WebUI shows an error 
> screen: “Unauthorized. Unable to validate the access token.”, with 2 links: 
> “log out” and “home”.
> If you click on the “home” link, *the browser enters in an infinite loop of 
> redirects between NiFi and OIDC Identity Provider.*
> The offending HTTP flows is:
>  * “home” link calls: GET /nifi
>  * Redirects to: GET /nifi/
>  ** asynchronously calls: GET /nifi-api/flow/current-user => failed HTTP 401
>  * Redirects to: GET /nifi/login
>  * Redirects to: GET <my_idp_url>/openid-connect/auth
>  * Redirects to: GET /nifi-api/access/oidc/callback
>  * Redirects to: GET /nifi
>  * Redirects to: GET /nifi/
>  ** asynchronously calls: GET /nifi-api/flow/current-user => failed HTTP 401
>  * [loop]
>  
> The stack trace of {{/nifi-api/flow/current-user}} call is:
>  
> {code:java}
> ERROR [NiFi Web Server-284] o.a.nifi.web.security.jwt.JwtService There was an 
> error validating the JWT io.jsonwebtoken.JwtException: Unable to validate the 
> access token.
>          at 
> org.apache.nifi.web.security.jwt.JwtService.parseTokenFromBase64EncodedString(JwtService.java:106)
>          at 
> org.apache.nifi.web.security.jwt.JwtService.getAuthenticationFromToken(JwtService.java:60)
>          at 
> org.apache.nifi.web.security.jwt.JwtAuthenticationProvider.authenticate(JwtAuthenticationProvider.java:48)
>          at 
> org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
>          at 
> org.apache.nifi.web.security.NiFiAuthenticationFilter.authenticate(NiFiAuthenticationFilter.java:78)
>          at 
> org.apache.nifi.web.security.NiFiAuthenticationFilter.doFilter(NiFiAuthenticationFilter.java:58)
>          at 
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
>          at 
> org.apache.nifi.web.security.NiFiAuthenticationFilter.authenticate(NiFiAuthenticationFilter.java:99)
>          at 
> org.apache.nifi.web.security.NiFiAuthenticationFilter.doFilter(NiFiAuthenticationFilter.java:58)
>          ...
> Caused by: io.jsonwebtoken.SignatureException: JWT signature does not match 
> locally computed signature. JWT validity cannot be asserted and should not be 
> trusted.
>          at 
> io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:342)
>          at 
> io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:458)
>          at 
> io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:518)
>          at 
> org.apache.nifi.web.security.jwt.JwtService.parseTokenFromBase64EncodedString(JwtService.java:102)
>          ...
> {code}
>  
>  
> In my opinion, there are 2 problems:
> h2. Problem 1
> The NiFi JWT token is used (and not replaced) by nfCanvas.init() even after 
> loadCurrentUser() failed with an authentication error (when GET 
> /nifi-api/flow/current-user returns 401).
> In such case, this token, stored in nfStorage (in Javascript Local Storage of 
> browser), should be cleared before redirecting to /nifi/login.
> h2. Problem 2
> The NiFi JWT token is not shared among NiFi cluster.
> This token is not the original id_token returned by the OIDC Identity 
> Provider, but a new one, generated by the NiFi instance on which the browser 
> was routed during the OIDC connection flow.
> This token is closely related to some data stored in H2 users database 
> (nifi-user-keys.h2.db).
> Its “KEY” table contains the following data for each user: email, a primary 
> key (auto increment) and a generated UUID.
> The NiFi JWT token contains (among other things) a copy of email and the 
> auto-incremented primary key. Moreover, this JWT is HS256-signed with UUID 
> key.
> *But, both primary key and UUID are not shared in NiFi cluster.*
> It seems to be the reason why WebUI must interrupt its polling to WebAPI: 
> stored JWT is no more valid on the new “selected” NiFi instance, to which the 
> load-balancer routes your browser.
> I think there are 3 solutions:
>  * Use a shared secret (from a new property in nifi.properties) to sign NiFi 
> JWT tokens. The uselessness of the primary key inside the token should be 
> checked;
>  * Synchronize the H2 users database among NiFi cluster;
>  * Replace the NiFi interal JWT token by the official OIDC JWT “id_token” on 
> every WebAPI calls.
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to