示例#1
0
        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));
            }
        }
示例#2
0
        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());
        }
示例#3
0
        // 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);
            });
        }
示例#4
0
        public OutgoingGrainCallAuthorizationFilter(IAccessTokenProvider accessTokenProvider,
                                                    IAccessTokenValidator accessTokenValidator,
                                                    OAuth2EndpointInfo oAuth2EndpointInfo, IAuthorizeHandler authorizeHandler,
                                                    ILoggerFactory loggerFactory) : base(accessTokenValidator, authorizeHandler)
        {
            _accessTokenProvider = accessTokenProvider;
            _oAuth2EndpointInfo  = oAuth2EndpointInfo;

            Logger = loggerFactory.CreateLogger <OutgoingGrainCallAuthorizationFilter>();
        }
示例#5
0
        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)));
        }
示例#6
0
        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);
                }
            }
        }
示例#7
0
 public static void StartClientWithRetries(out IClusterClient client,
                                           IHttpContextAccessor httpContextAccessor, OAuth2EndpointInfo oAuth2EndpointInfo)
 {
     if (_client != null && _client.IsInitialized)
     {
         client = _client;
     }
     _client = TryToConnect(httpContextAccessor, oAuth2EndpointInfo);
     client  = _client;
 }
示例#8
0
        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));
        }