/// <summary>
        /// Get the stored tokens associated with the http context.
        /// </summary>
        /// <param name="context">The current http context.</param>
        /// <param name="authority">The authority of the OIDC configuration.</param>
        /// <param name="clientId">The OIDC client id of this application.</param>
        /// <param name="clientSecret">The OIDC client secret of this application.</param>
        /// <param name="resource">The OIDC resource identifier.</param>
        /// <returns>A tuple with the id and access tokens.</returns>
        public static async Task <(string idToken, string accessToken)> GetTokensFromContext(
            HttpContext context,
            string authority,
            string clientId,
            string clientSecret,
            string resource
            )
        {
            var authContext  = new AuthenticationContext(authority, AuthPropertiesTokenCache.ForApiCalls(context, CookieAuthenticationDefaults.AuthenticationScheme));
            var credential   = new ClientCredential(clientId, clientSecret);
            var userObjectId = context.User.FindFirst(ObjectIdentifierClaimUri).Value;
            var result       = await authContext.AcquireTokenSilentAsync(
                resource : resource,
                clientCredential : credential,
                userId : new UserIdentifier(userObjectId, UserIdentifierType.UniqueId)
                );

            return(
                idToken : result.IdToken,
                accessToken : result.AccessToken
                );
        }
Пример #2
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure <CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded    = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(options =>
            {
                options.DefaultScheme          = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
            {
                Configuration.Bind("OpenId", options);

                // We need the authorization code to get both id and access tokens
                options.ResponseType = "code id_token";

                // Saves the access token in the cookies
                options.SaveTokens = true;

                // Session lifetime will match the tokens'
                options.UseTokenLifetime = true;

                // WorkflowGen's GraphQL API doesn't have a /userinfo endpoint
                // like described in the OpenID Connect protocol. This prevents
                // the middleware from requesting from this endpoint.
                options.GetClaimsFromUserInfoEndpoint = false;
                options.TokenValidationParameters     = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                };

                // Adds an action to map custom claims from additional scopes.
                options.ClaimActions.MapUniqueJsonKey("sub", "sub");
                options.ClaimActions.MapUniqueJsonKey("name", "name");
                options.ClaimActions.MapUniqueJsonKey("given_name", "given_name");
                options.ClaimActions.MapUniqueJsonKey("family_name", "family_name");
                options.ClaimActions.MapUniqueJsonKey("profile", "profile");
                options.ClaimActions.MapUniqueJsonKey("email", "email");

                // Ensures that only the following scopes are requested.
                // If you need more, add them here.
                options.Scope.Clear();
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                options.Scope.Add("email");

                options.Events = new OpenIdConnectEvents
                {
                    // Manually handles the exchange of the authorization code
                    // for tokens (id token and access token)
                    OnAuthorizationCodeReceived = async context =>
                    {
                        var request    = context.HttpContext.Request;
                        var currentUri = UriHelper.BuildAbsolute(
                            scheme: request.Scheme,
                            host: request.Host,
                            pathBase: request.PathBase,
                            path: request.Path
                            );
                        var credential  = new ClientCredential(options.ClientId, options.ClientSecret);
                        var authContext = new AuthenticationContext(
                            options.Authority,
                            tokenCache: AuthPropertiesTokenCache.ForCodeRedemption(context.Properties)
                            );
                        var result = await authContext.AcquireTokenByAuthorizationCodeAsync(
                            authorizationCode: context.ProtocolMessage.Code,
                            redirectUri: new Uri(currentUri),
                            credential,
                            resource: options.Resource
                            );

                        context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                    }
                };
            });
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            services.AddTransient <IGraphQLClient, GraphQLHttpClient>(provider =>
            {
                // Retrieve the access token from the TokenCache.
                var httpContextAccessor = provider.GetService <IHttpContextAccessor>();
                var client = new GraphQLHttpClient(Configuration["OpenId:Resource"]);
                (var _, var accessToken) = Utilities.GetTokensFromContext(
                    context: httpContextAccessor.HttpContext,
                    authority: Configuration["OpenId:Authority"],
                    clientId: Configuration["OpenId:ClientId"],
                    clientSecret: Configuration["OpenId:ClientSecret"],
                    resource: Configuration["OpenId:Resource"]
                    ).Result;

                client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
                return(client);
            });
            services.AddMvc(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                             .RequireAuthenticatedUser()
                             .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }