private string resolveTokens(string stringWithTokens) { string resolvedString = stringWithTokens; #region Resolve From Config MatchCollection matchedConfigTokens = Regex.Matches(resolvedString, configPattern, RegexOptions.None); foreach (Match match in matchedConfigTokens) { string token = match.Value.Replace("$Config.", "").Replace("$", ""); string tokenValue = _config["APIProxySettings:clientSettings:" + token]; Console.WriteLine("token : {0} value : {1}", match.Value, tokenValue); resolvedString = resolvedString.Replace(match.Value, tokenValue); } #endregion #region Resolve From Server MatchCollection matchedServerTokens = Regex.Matches(resolvedString, serverPattern, RegexOptions.None); foreach (Match match in matchedServerTokens) { string token = match.Value.Replace("$Server.", "").Replace("$", ""); string tokenValue = null; switch (token.ToLower().Trim()) { case "datetime": { tokenValue = DateTime.Now.ToString(); break; } default: { throw new Exception(string.Format("Unrecognized server token {0}", match.Value)); } } Console.WriteLine("token : {0} value : {1}", match.Value, tokenValue); resolvedString = resolvedString.Replace(match.Value, tokenValue); } #endregion #region Resolve From JWT MatchCollection matchedJwtTokens = Regex.Matches(resolvedString, jwtPattern, RegexOptions.None); if (!_isAuthenticatedSession) { throw new Exception("Request needs an authenticated session for token replacement"); } else { foreach (Match match in matchedJwtTokens) { string token = match.Value.Replace("$Jwt.", "").Replace("$", ""); Claim requestedClaim = _JWTHelper.getClaim(token); if (requestedClaim != null) { string tokenValue = requestedClaim.Value; Console.WriteLine("token : {0} value : {1}", match.Value, tokenValue); resolvedString = resolvedString.Replace(match.Value, tokenValue); } else { throw new Exception(string.Format("Request needs an authenticated session with valid claim name for token replacement. Claim name {0}", token)); } } } #endregion return(resolvedString); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = Configuration["Jwt:Issuer"], ValidAudience = Configuration["Jwt:Issuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])) }; options.Events = new JwtBearerEvents { // Decrypt the JWT so it can be processed by Authorize logic. OnMessageReceived = context => { string jwt = String.Empty; string hdrJWT = String.Empty; ICryptoHelper _cryptoHelper = context.HttpContext.GetInstanceFromContext <ICryptoHelper>(); IJWTHelper _JWTHelper = context.HttpContext.GetInstanceFromContext <IJWTHelper>(); try { hdrJWT = _JWTHelper.getBearerHeaderValue(context.Request.Headers); jwt = _cryptoHelper.decrypt(hdrJWT); context.Token = jwt; } catch (Exception ex) { string msg = $"ERROR: Missing or invalid JWT. EXCEPTION: {ex.Message} JWT: {hdrJWT} DECRYPTED: {jwt}"; Console.WriteLine("USER AUTHENTICATION", "Startup.cs", "ConfigureServices.OnMessageReceived", msg, ex); } return(Task.FromResult(0)); }, // On valid token received, this fires. Useful for debugging purposes. OnTokenValidated = context => { string plainTextJWT = context.SecurityToken.ToString(); return(Task.FromResult(0)); }, // On authentication failures, redirect to the public login page OnChallenge = context => { ICryptoHelper _cryptoHelper = context.HttpContext.GetInstanceFromContext <ICryptoHelper>(); IJWTHelper _JWTHelper = context.HttpContext.GetInstanceFromContext <IJWTHelper>(); // If no path was requested, get the default landing page. Otherwise // use the requested path ensuring the correct context root is included. PathString currenturi = context.Request.Path == null ? new PathString(Configuration["AppSettings:homePageUrl"]) : new PathString(Configuration["AppSettings:appRootPath"] + context.Request.Path); // Pass the originally requested page as a querystring parm preserving its querystring if present string q = context.HttpContext.Request.QueryString.HasValue ? WebUtility.UrlEncode(context.HttpContext.Request.QueryString.ToString()) : String.Empty; string redirectUrl = Configuration["AppSettings:loginUrl"] + QueryString.Create("ReturnUrl", currenturi) + q; // Save the originally requested page in a cookie context.Response.Cookies.Append("requestedurl", currenturi); context.Response.Redirect(redirectUrl); context.HandleResponse(); string hdrJWT = string.Empty; string jwtDetail = string.Empty; try { hdrJWT = _JWTHelper.getBearerHeaderValue(context.Request.Headers); if (!String.IsNullOrEmpty(hdrJWT)) { string format = "yyyy-MM-dd HH:mm:ss:fffffff"; string currentUTC = DateTime.UtcNow.ToString(format); string detailMsg = context.AuthenticateFailure.Message; string jwtEXP = _JWTHelper.getClaim(JwtRegisteredClaimNames.Exp.ToString()).Value; string jwtExpAsDate = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddSeconds(Convert.ToDouble(jwtEXP)).ToString(format); jwtDetail = $"JWT Expires: {jwtExpAsDate} JWT EXP: {jwtEXP} Current Time: {currentUTC} Auth Error: {detailMsg} "; } } catch (Exception ex) { string setBreakPointHere = ex.Message; } string msg = String.IsNullOrEmpty(context.ErrorDescription) ? String.Empty : $"EXCEPTION: {context.Error} - {context.ErrorDescription}"; string errorMsg = $"ERROR: Missing or invalid JWT. {msg} JWT: {hdrJWT} DETAIL: {jwtDetail}"; Console.WriteLine("USER AUTHENTICATION", "Startup.cs", "ConfigureServices.OnChallenge", errorMsg); return(Task.FromResult(0)); } }; }); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton <ICryptoHelper, CryptoHelper>(); services.AddScoped <ICookieHelper, CookieHelper>(); services.AddScoped <IJWTHelper, JWTHelper>(); services.AddScoped <IProxyHelper, ProxyHelper>(); // Convert all generated URLs to lowercase. services.AddRouting(options => { options.LowercaseUrls = true; }); // Default all controller actions to require authentication unless adorned with [AllowAnonymous]. services.AddMvc(config => { var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); config.Filters.Add(new AuthorizeFilter(policy)); }); }