diff options
Diffstat (limited to 'solr-8.3.1/server/solr-webapp/webapp/js/angular/controllers/login.js')
| -rw-r--r-- | solr-8.3.1/server/solr-webapp/webapp/js/angular/controllers/login.js | 317 | 
1 files changed, 317 insertions, 0 deletions
diff --git a/solr-8.3.1/server/solr-webapp/webapp/js/angular/controllers/login.js b/solr-8.3.1/server/solr-webapp/webapp/js/angular/controllers/login.js new file mode 100644 index 000000000..8127c6fda --- /dev/null +++ b/solr-8.3.1/server/solr-webapp/webapp/js/angular/controllers/login.js @@ -0,0 +1,317 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements.  See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License.  You may obtain a copy of the License at + +     http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('LoginController', +    ['$scope', '$routeParams', '$rootScope', '$location', '$window', 'AuthenticationService', 'Constants', +      function ($scope, $routeParams, $rootScope, $location, $window, AuthenticationService, Constants) { +        $scope.resetMenu("login", Constants.IS_ROOT_PAGE); +        $scope.subPath = $routeParams.route; +        $rootScope.exceptions = {}; + +        // Session variables set in app.js 401 interceptor +        var wwwAuthHeader = sessionStorage.getItem("auth.wwwAuthHeader"); +        var authScheme = sessionStorage.getItem("auth.scheme"); +        if (wwwAuthHeader) { +          // Parse www-authenticate header +          var wwwHeader = wwwAuthHeader.match(/(\w+)(\s+)?(.*)/); +          authScheme = "unknown"; +          var authParams = {}; +          if (wwwHeader && wwwHeader.length >= 1) +            authScheme = wwwHeader[1];  +          if (wwwHeader && wwwHeader.length >= 3) +            authParams = www_auth_parse_params(wwwHeader[3]); +          if (typeof authParams === 'string' || authParams instanceof String) { +            $scope.authParamsError = authParams; +          } else { +            $scope.authParamsError = undefined; +          } +          var realm = authParams['realm']; +          sessionStorage.setItem("auth.realm", realm); +          if (authScheme === 'Basic' || authScheme === 'xBasic') { +            authScheme = 'Basic'; +          } +          sessionStorage.setItem("auth.scheme", authScheme); +        } + +        var supportedSchemes = ['Basic', 'Bearer', 'Negotiate']; +        $scope.authSchemeSupported = supportedSchemes.includes(authScheme); + +        if (authScheme === 'Bearer') { +          // Check for OpenId redirect response +          var errorText = ""; +          $scope.isCallback = false; +          if ($scope.subPath === 'callback') { +            $scope.isCallback = true; +            var hash = $location.hash(); +            var hp = AuthenticationService.decodeHashParams(hash); +            var expectedState = sessionStorage.getItem("auth.stateRandom") + "_" + sessionStorage.getItem("auth.location"); +            sessionStorage.setItem("auth.state", "error"); +            if (hp['access_token'] && hp['token_type'] && hp['state']) { +              // Validate state +              if (hp['state'] !== expectedState) { +                $scope.error = "Problem with auth callback"; +                console.log("Expected state param " + expectedState + " but got " + hp['state']); +                errorText += "Invalid values in state parameter. "; +              } +              // Validate token type +              if (hp['token_type'].toLowerCase() !== "bearer") { +                console.log("Expected token_type param 'bearer', but got " + hp['token_type']); +                errorText += "Invalid values in token_type parameter. "; +              } +              // Unpack ID token and validate nonce, get username +              if (hp['id_token']) { +                var idToken = hp['id_token'].split("."); +                if (idToken.length === 3) { +                  var payload = AuthenticationService.decodeJwtPart(idToken[1]); +                  if (!payload['nonce'] || payload['nonce'] !== sessionStorage.getItem("auth.nonce")) { +                    errorText += "Invalid 'nonce' value, possible attack detected. Please log in again. "; +                  } + +                  if (errorText === "") { +                    sessionStorage.setItem("auth.username", payload['sub']); +                    sessionStorage.setItem("auth.header", "Bearer " + hp['access_token']); +                    sessionStorage.removeItem("auth.statusText"); +                    sessionStorage.removeItem("auth.stateRandom"); +                    sessionStorage.removeItem("auth.wwwAuthHeader"); +                    console.log("User " + payload['sub'] + " is logged in"); +                    var redirectTo = sessionStorage.getItem("auth.location"); +                    console.log("Redirecting to stored location " + redirectTo); +                    sessionStorage.setItem("auth.state", "authenticated"); +                    sessionStorage.removeItem("http401"); +                    $location.path(redirectTo).hash(""); +                  } +                } else { +                  console.log("Expected JWT compact id_token param but got " + idToken); +                  errorText += "Invalid values in id_token parameter. "; +                } +              } else { +                console.log("Callback was missing the id_token parameter, could not validate nonce."); +                errorText += "Callback was missing the id_token parameter, could not validate nonce. "; +              } +              if (hp['access_token'].split(".").length !== 3) { +                console.log("Expected JWT compact access_token param but got " + hp['access_token']); +                errorText += "Invalid values in access_token parameter. "; +              } +              if (errorText !== "") { +                $scope.error = "Problems with OpenID callback"; +                $scope.errorDescription = errorText; +                $scope.http401 = "true"; +              } +              // End callback processing +            } else if (hp['error']) { +              // The callback had errors +              console.log("Error received from idp: " + hp['error']); +              var errorDescriptions = {}; +              errorDescriptions['invalid_request'] = "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."; +              errorDescriptions['unauthorized_client'] = "The client is not authorized to request an access token using this method."; +              errorDescriptions['access_denied'] = "The resource owner or authorization server denied the request."; +              errorDescriptions['unsupported_response_type'] = "The authorization server does not support obtaining an access token using this method."; +              errorDescriptions['invalid_scope'] = "The requested scope is invalid, unknown, or malformed."; +              errorDescriptions['server_error'] = "The authorization server encountered an unexpected condition that prevented it from fulfilling the request."; +              errorDescriptions['temporarily_unavailable'] = "The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server."; +              $scope.error = "Callback from Id Provider contained error. "; +              if (hp['error_description']) { +                $scope.errorDescription = decodeURIComponent(hp['error_description']); +              } else { +                $scope.errorDescription = errorDescriptions[hp['error']]; +              } +              if (hp['error_uri']) { +                $scope.errorDescription += " More information at " + hp['error_uri'] + ". "; +              } +              if (hp['state'] !== expectedState) { +                $scope.errorDescription += "The state parameter returned from ID Provider did not match the one we sent."; +              } +              sessionStorage.setItem("auth.state", "error"); +            } +          } +        } + +        if (errorText === "" && !$scope.error && authParams) { +          $scope.error = authParams['error']; +          $scope.errorDescription = authParams['error_description']; +          $scope.authData = AuthenticationService.getAuthDataHeader(); +        } +         +        $scope.authScheme = sessionStorage.getItem("auth.scheme"); +        $scope.authRealm = sessionStorage.getItem("auth.realm"); +        $scope.wwwAuthHeader = sessionStorage.getItem("auth.wwwAuthHeader"); +        $scope.statusText = sessionStorage.getItem("auth.statusText"); +        $scope.authLocation = sessionStorage.getItem("auth.location"); +        $scope.authLoggedinUser = sessionStorage.getItem("auth.username"); +        $scope.authHeader = sessionStorage.getItem("auth.header"); + +        $scope.login = function () { +          AuthenticationService.SetCredentials($scope.username, $scope.password); +          $location.path($scope.authLocation); // Redirect to the location that caused the login prompt +        }; + +        $scope.logout = function() { +          // reset login status +          AuthenticationService.ClearCredentials(); +          $location.path("/"); +        }; + +        $scope.jwtLogin = function () { +          var stateRandom = Math.random().toString(36).substr(2); +          sessionStorage.setItem("auth.stateRandom", stateRandom); +          var authState = stateRandom + "_" + sessionStorage.getItem("auth.location"); +          var authNonce = Math.random().toString(36).substr(2) + Math.random().toString(36).substr(2) + Math.random().toString(36).substr(2); +          sessionStorage.setItem("auth.nonce", authNonce); +          var params = { +            "response_type" : "id_token token", +            "client_id" : $scope.authData['client_id'], +            "redirect_uri" : $window.location.href.split('#')[0], +            "scope" : "openid " + $scope.authData['scope'], +            "state" : authState, +            "nonce" : authNonce +          }; + +          var endpointBaseUrl = $scope.authData['authorizationEndpoint']; +          var loc = endpointBaseUrl + "?" + paramsToString(params); +          console.log("Redirecting to " + loc); +          sessionStorage.setItem("auth.state", "expectCallback"); +          $window.location.href = loc; + +          function paramsToString(params) { +            var arr = []; +            for (var p in params) { +               if( params.hasOwnProperty(p) ) { +                 arr.push(p + "=" + encodeURIComponent(params[p])); +               }  +             } +             return arr.join("&"); +          } +        }; + +        $scope.jwtIsLoginNode = function() { +          var redirect = $scope.authData ? $scope.authData['redirect_uris'] : undefined; +          if (redirect && Array.isArray(redirect) && redirect.length > 0) { +            var isLoginNode = false; +            redirect.forEach(function(uri) { // Check that current node URL is among the configured callback URIs +              if ($window.location.href.startsWith(uri)) isLoginNode = true; +            }); +            return isLoginNode;  +          } else { +            return true; // no redirect UIRs configured, all nodes are potential login nodes +          } +        }; + +        $scope.jwtFindLoginNode = function() { +          var redirect = $scope.authData ? $scope.authData['redirect_uris'] : undefined; +          if (redirect && Array.isArray(redirect) && redirect.length > 0) { +            var loginNode = redirect[0]; +            redirect.forEach(function(uri) { // if current node is in list, return its callback uri +              if ($window.location.href.startsWith(uri)) loginNode = uri; +            }); +            return loginNode;  +          } else { +             return $window.location.href.split('#')[0]; // Return base url of current URL as the url to use  +          } +        }; + +        // Redirect to login node if this is not a valid one +        $scope.jwtGotoLoginNode = function() { +          if (!$scope.jwtIsLoginNode()) { +            $window.location.href = $scope.jwtFindLoginNode(); +          } +        }; + +        $scope.jwtLogout = function() { +          // reset login status +          AuthenticationService.ClearCredentials(); +          $location.path("/"); +        }; +         +        $scope.isLoggedIn = function() { +          return (sessionStorage.getItem("auth.username") !== null); +        }; +      }]); + +// This function is copied and adapted from MIT-licensed https://github.com/randymized/www-authenticate/blob/master/lib/parsers.js +www_auth_parse_params= function (header) { +  // This parser will definitely fail if there is more than one challenge +  var params = {}; +  var tok, last_tok, _i, _len, key, value; +  var state= 0;   //0: token, +  var m= header.split(/([",=])/); +  for (_i = 0, _len = m.length; _i < _len; _i++) { +    last_tok= tok; +    tok = m[_i]; +    if (!tok.length) continue; +    switch (state) { +      case 0: // token +        key= tok.trim(); +        state= 1; // expect equals +        continue; +      case 1: // expect equals +        if ('=' != tok) return 'Equal sign was expected after '+key; +        state= 2; +        continue; +      case 2: // expect value +        if ('"' == tok) { +          value= ''; +          state= 3; // expect quoted +          continue; +        } +        else { +          params[key]= value= tok.trim(); +          state= 9; // expect comma or end +          continue; +        } +      case 3: // handling quoted string +        if ('"' == tok) { +          state= 8; // end quoted +          continue; +        } +        else { +          value+= tok; +          state= 3; // continue accumulating quoted string +          continue; +        } +      case 8: // end quote encountered +        if ('"' == tok) { +          // double quoted +          value+= '"'; +          state= 3; // back to quoted string +          continue; +        } +        if (',' == tok) { +          params[key]= value; +          state= 0; +          continue; +        } +        else { +          return 'Unexpected token ('+tok+') after '+value+'"'; +        } +        continue; +      case 9: // expect commma +        if (',' != tok) return 'Comma expected after '+value; +        state= 0; +        continue; +    } +  } +  switch (state) {  // terminal state +    case 0:   // Empty or ignoring terminal comma +    case 9:   // Expecting comma or end of header +      return params; +    case 8:   // Last token was end quote +      params[key]= value; +      return params; +    default: +      return 'Unexpected end of www-authenticate value.'; +  } +};  | 
