protected async Task AuthorizeAsync(IGrainCallContext grainCallContext, string accessToken, OAuth2EndpointInfo oAuth2EndpointInfo) { if (string.IsNullOrEmpty(accessToken)) { throw new ArgumentNullException($"{nameof(accessToken)}"); } if (oAuth2EndpointInfo == null) { throw new ArgumentNullException($"{nameof(oAuth2EndpointInfo)}"); } var accessTokenValidationResult = await _accessTokenValidator.Validate(accessToken, oAuth2EndpointInfo); if (accessTokenValidationResult.IsValid) { IEnumerable <IAuthorizeData> grainAuthorizeData = null; var grainMethodAuthorizeData = grainCallContext.InterfaceMethod.GetCustomAttributes <AuthorizeAttribute>(); if (grainCallContext.InterfaceMethod.ReflectedType != null) { grainAuthorizeData = grainCallContext.InterfaceMethod.ReflectedType.GetCustomAttributes <AuthorizeAttribute>(); } await _authorizeHandler.AuthorizeAsync(accessTokenValidationResult.Claims, grainAuthorizeData, grainMethodAuthorizeData); } else { throw new OrleansClusterUnauthorizedAccessException("Invalid Access Token.", new InvalidAccessTokenException(accessTokenValidationResult.InvalidValidationMessage)); } }
private static IClusterClient Build(IHttpContextAccessor contextAccessor, OAuth2EndpointInfo oAuth2EndpointInfo) { var builder = new ClientBuilder() .UseLocalhostClustering() .Configure <ClusterOptions>(options => { options.ClusterId = "Orleans.Security.Test"; options.ServiceId = "ServiceId1"; }) .ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(IUserGrain).Assembly).WithReferences()) .ConfigureLogging(logging => logging.AddConsole()) .ConfigureServices(services => { services.AddOrleansClusterAuthorization(options => { options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Admin")); options.AddPolicy("ManagerPolicy", policy => policy.RequireRole("Manager")); }); services.AddSingleton <IOutgoingGrainCallFilter, OutgoingGrainCallAuthorizationFilter>(); services.AddSingleton <Func <IHttpContextAccessor> >(serviceProvider => () => contextAccessor); services.AddSingleton(oAuth2EndpointInfo); services.AddScoped <IAccessTokenProvider, AspNetCoreAccessTokenProvider>(); }); return(builder.Build()); }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { var oAuth2EndpointInfo = new OAuth2EndpointInfo("https://*****:*****@"C%#4>#2x-kH(d9TuKqs?3Wt@NLT.\x$["); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddIdentityServerAuthentication(options => { options.SupportedTokens = SupportedTokens.Both; options.Authority = oAuth2EndpointInfo.AuthorityUrl; options.ApiName = oAuth2EndpointInfo.ClientScopeName; options.ApiSecret = oAuth2EndpointInfo.ClientSecret; options.SaveToken = true; }); services.AddMvcCore().AddAuthorization().AddJsonFormatters(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.TryAddSingleton <IHttpContextAccessor, HttpContextAccessor>(); // ReSharper disable once RedundantTypeArgumentsOfMethod services.AddSingleton <IClusterClient>(serviceProvider => { OrleansClusterClientProvider.StartClientWithRetries(out var client, serviceProvider.GetService <IHttpContextAccessor>(), oAuth2EndpointInfo); return(client); }); }
public OutgoingGrainCallAuthorizationFilter(IAccessTokenProvider accessTokenProvider, IAccessTokenValidator accessTokenValidator, OAuth2EndpointInfo oAuth2EndpointInfo, IAuthorizeHandler authorizeHandler, ILoggerFactory loggerFactory) : base(accessTokenValidator, authorizeHandler) { _accessTokenProvider = accessTokenProvider; _oAuth2EndpointInfo = oAuth2EndpointInfo; Logger = loggerFactory.CreateLogger <OutgoingGrainCallAuthorizationFilter>(); }
public Task <AccessTokenValidationResult> Validate(string accessToken, OAuth2EndpointInfo oAuth2EndpointInfo) { var userName = TestContext.CurrentContext.Test.FullName; var loggedInUser = (int)LoggedInUser; if (!AuthorizationTestConfig.Claims.ContainsKey(loggedInUser)) { throw new InvalidOperationException($"Invalid LoggedInUser value for {userName}."); } // ReSharper disable once SuggestVarOrType_Elsewhere IEnumerable <Claim> claims = AuthorizationTestConfig.Claims[loggedInUser]; return(Task.FromResult(AccessTokenValidationResult.CreateSuccess(AccessTokenType.Jwt, claims))); }
private static IClusterClient TryToConnect(IHttpContextAccessor httpContextAccessor, OAuth2EndpointInfo oAuth2EndpointInfo) { var attempt = 0; //var logger = loggerFactory.CreateLogger<OrleansClusterClientProvider>(); while (true) { try { var client = Build(httpContextAccessor, oAuth2EndpointInfo); client.Connect().Wait(); //logger.LogInformation("Client successfully connect to silo host"); return(client); } catch (AggregateException ex) { if (ex.InnerException is SiloUnavailableException) { attempt++; //logger.LogError(ex, ex.Message); if (attempt > _initializeAttemptsBeforeFailing) { throw; } Task.Delay(TimeSpan.FromSeconds(1)); } //logger.LogError(ex, ex.Message); } } }
public static void StartClientWithRetries(out IClusterClient client, IHttpContextAccessor httpContextAccessor, OAuth2EndpointInfo oAuth2EndpointInfo) { if (_client != null && _client.IsInitialized) { client = _client; } _client = TryToConnect(httpContextAccessor, oAuth2EndpointInfo); client = _client; }
public async Task <AccessTokenValidationResult> Validate(string accessToken, OAuth2EndpointInfo oAuth2EndpointInfo) { //TODO: Implement caching functionality to improve performance. if (string.IsNullOrEmpty(accessToken)) { throw new ArgumentException($"The value of {nameof(accessToken)} can't be null or empty."); } var accessTokenType = AccessTokenType.Reference; var jwtTokenParser = new JwtTokenParser(); if (jwtTokenParser.IsAccessTokenJwt(accessToken)) { accessTokenType = AccessTokenType.Jwt; } var handler = new HttpClientHandler(); #if STAGE || DEBUG #region Certificate validation for a self-signed certificate #if !STAGE && !DEBUG #error Disable certificate validation in production deployment ! #endif handler.ServerCertificateCustomValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { if (sslPolicyErrors != System.Net.Security.SslPolicyErrors.None) { _logger.LogWarning("Remote certificate validation failed, it is explicitly disabled in code."); } return(true); }; #endregion #endif var httpClient = new HttpClient(handler); var response = await httpClient.IntrospectTokenAsync(new TokenIntrospectionRequest { Address = $"{oAuth2EndpointInfo.AuthorityUrl}/connect/introspect", ClientId = oAuth2EndpointInfo.ClientScopeName, Token = accessToken, ClientSecret = oAuth2EndpointInfo.ClientSecret, }); // ReSharper disable once InvertIf if (!response.IsError) { return(AccessTokenValidationResult.CreateSuccess(accessTokenType, response.Claims)); } var nameOfTokenType = accessTokenType == AccessTokenType.Jwt ? "JWT" : "Reference"; _logger.LogTrace(LoggingEvents.AccessTokenValidationFailed, $"{LoggingEvents.AccessTokenValidationFailed.Name} Token type: {nameOfTokenType} " + $"Reason: {response.Error} " + $"Token value: {accessToken}"); return(AccessTokenValidationResult.CreateFailed(response.Error)); }