public async Task<IActionResult> Complete(string code, string error, string error_description, string resource, string state) {
            var token = state;
            if(error.IsNotNullOrEmpty() || error_description.IsNotNullOrEmpty()) {
                _logger.Log(x => x.Error, () => string.Format("Error completing registration - {0}", new { token, error, error_description, resource, state }));
                return View("RegistrationError", new RegistrationErrorModel(error, error_description));
            }

            var registrationRequest = await _database.RegistrationRequests.FirstOrDefaultAsync(x => x.Token == state);

            if(registrationRequest == null) {
                _logger.Log(x => x.Error, () => string.Format("Unknown registration request - {0}", new { token }));
                return View("RegistrationRequestUnknown");
            }

            _logger.Log(x => x.Information, () => string.Format("Completing registration process - {0}", new { registrationRequest.Name, registrationRequest.Token }));

            var authority = AuthorityUrl.FormatUrlWith("common");

            var clientCredential = new ClientCredential(_settings.ClientID, _settings.ClientSecret);
            var authenticationContext = new AuthenticationContext(authority);
            var authenticationResult = authenticationContext.AcquireTokenByAuthorizationCode(code, new Uri(Request.GetUri().GetLeftPart(UriPartial.Path)), clientCredential);

            await RegisterAsync(registrationRequest.Name, authenticationResult.TenantId, authenticationResult.UserInfo.DisplayableId, authenticationResult.UserInfo.IdentityProvider);

            return View("TenantRegistrationSuccess");
        }
Пример #2
0
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId              = clientId,
                Authority             = Authority,
                PostLogoutRedirectUri = postLogoutRedirectUri,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    //
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                    //

                    AuthorizationCodeReceived = (context) =>
                    {
                        var code = context.Code;

                        if (certName.Length != 0)
                        {
                            // Create a Client Credential Using a Certificate
                            //
                            // Initialize the Certificate Credential to be used by ADAL.
                            // First find the matching certificate in the cert store.
                            //

                            X509Certificate2 cert = null;
                            X509Store store       = new X509Store(StoreLocation.CurrentUser);
                            try
                            {
                                store.Open(OpenFlags.ReadOnly);
                                // Place all certificates in an X509Certificate2Collection object.
                                X509Certificate2Collection certCollection = store.Certificates;
                                // Find unexpired certificates.
                                X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
                                // From the collection of unexpired certificates, find the ones with the correct name.
                                X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, false);
                                if (signingCert.Count == 0)
                                {
                                    // No matching certificate found.
                                    return(Task.FromResult(0));
                                }
                                // Return the first certificate in the collection, has the right name and is current.
                                cert = signingCert[0];
                            }
                            finally
                            {
                                store.Close();
                            }

                            // Then create the certificate credential.
                            ClientAssertionCertificate credential = new ClientAssertionCertificate(clientId, cert);

                            string userObjectID = context.AuthenticationTicket.Identity.FindFirst(
                                "http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
                            AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));
                            AuthenticationResult result       = authContext.AcquireTokenByAuthorizationCode(
                                code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
                            AuthenticationHelper.token = result.AccessToken;
                        }
                        else
                        {
                            // Create a Client Credential Using an Application Key
                            ClientCredential credential = new ClientCredential(clientId, appKey);
                            string userObjectID         = context.AuthenticationTicket.Identity.FindFirst(
                                "http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
                            AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));
                            AuthenticationResult result       = authContext.AcquireTokenByAuthorizationCode(
                                code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
                            AuthenticationHelper.token = result.AccessToken;
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
Пример #3
0
        public void ConfigureAuth(IAppBuilder app)
        {
            string clientId        = ConfigurationManager.AppSettings["ida:ClientID"];
            string appKey          = ConfigurationManager.AppSettings["ida:Password"];
            string graphResourceID = "https://graph.windows.net";
            //fixed address for multitenant apps in the public cloud
            string Authority = "https://login.windows.net/common/";

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions {
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                Client_Id = clientId,
                Authority = Authority,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // instead of using the default validation (validating against a single issuer value, as we do in line of business apps),
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    AccessCodeReceived = (context) =>
                    {
                        var code = context.Code;

                        ClientCredential credential = new ClientCredential(clientId, appKey);
                        string tenantID             = context.ClaimsIdentity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                        string signedInUserID       = context.ClaimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;

                        AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantID));
                        AuthenticationResult result       = authContext.AcquireTokenByAuthorizationCode(
                            code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceID);



                        TokenCacheEntry tce = new TokenCacheEntry
                        {
                            SignedInUser       = signedInUserID,
                            TokenRequestorUser = result.UserInfo.UserId,
                            ResourceID         = graphResourceID,
                            AccessToken        = result.AccessToken,
                            RefreshToken       = result.RefreshToken,
                            Expiration         = result.ExpiresOn.AddMinutes(-5)
                        };
                        var existing = db.TokenCache.FirstOrDefault(a => (a.SignedInUser == signedInUserID) && (a.ResourceID == graphResourceID));
                        if (existing != null)
                        {
                            db.TokenCache.Remove(existing);
                        }
                        db.TokenCache.Add(tce);
                        db.SaveChanges();
                        return(Task.FromResult(0));
                    },
                    RedirectToIdentityProvider = (context) =>
                    {
                        // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                        // this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
                        // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                        string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                        context.ProtocolMessage.Redirect_Uri             = appBaseUrl + "/";
                        context.ProtocolMessage.Post_Logout_Redirect_Uri = appBaseUrl;
                        return(Task.FromResult(0));
                    },
                    // we use this notification for injecting our custom logic
                    SecurityTokenValidated = (context) =>
                    {
                        // retriever caller data from the incoming principal
                        string issuer   = context.AuthenticationTicket.Identity.FindFirst("iss").Value;
                        string UPN      = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
                        string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

                        if (
                            // the caller comes from an admin-consented, recorded issuer
                            (db.Tenants.FirstOrDefault(a => ((a.IssValue == issuer) && (a.AdminConsented))) == null)
                            // the caller is recorded in the db of users who went through the individual onboardoing
                            && (db.Users.FirstOrDefault(b => ((b.UPN == UPN) && (b.TenantID == tenantID))) == null)
                            )
                        {
                            // the caller was neither from a trusted issuer or a registered user - throw to block the authentication flow
                            throw new System.IdentityModel.Tokens.SecurityTokenValidationException();
                        }
                        return(Task.FromResult(0));
                    },
                    AuthenticationFailed = (context) =>
                    {
                        context.Redirect("/Home/Error");
                        return(Task.FromResult(0));
                    }
                }
            });
        }
Пример #4
0
        public void ConfigureAuth(IAppBuilder app)
        {
            string ClientId                       = ConfigurationManager.AppSettings["ida:ClientID"];
            string Password                       = ConfigurationManager.AppSettings["ida:Password"];
            string Authority                      = string.Format(ConfigurationManager.AppSettings["ida:Authority"], "common");
            string GraphAPIIdentifier             = ConfigurationManager.AppSettings["ida:GraphAPIIdentifier"];
            string AzureResourceManagerIdentifier = ConfigurationManager.AppSettings["ida:AzureResourceManagerIdentifier"];

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions {
            });
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId  = ClientId,
                Authority = Authority,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    RedirectToIdentityProvider = (context) =>
                    {
                        // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                        // this allows you to deploy your app (to Azure Web Sites, for example) without having to change settings
                        // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                        //string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;

                        object obj = null;
                        if (context.OwinContext.Environment.TryGetValue("Authority", out obj))
                        {
                            string authority = obj as string;
                            if (authority != null)
                            {
                                context.ProtocolMessage.IssuerAddress = authority;
                            }
                        }
                        if (context.OwinContext.Environment.TryGetValue("DomainHint", out obj))
                        {
                            string domainHint = obj as string;
                            if (domainHint != null)
                            {
                                context.ProtocolMessage.SetParameter("domain_hint", domainHint);
                            }
                        }
                        context.ProtocolMessage.RedirectUri           = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path);
                        context.ProtocolMessage.PostLogoutRedirectUri = new UrlHelper(HttpContext.Current.Request.RequestContext).Action
                                                                            ("Index", "Home", null, HttpContext.Current.Request.Url.Scheme);
                        //context.ProtocolMessage.Resource = GraphAPIIdentifier;
                        context.ProtocolMessage.Resource = AzureResourceManagerIdentifier;
                        return(Task.FromResult(0));
                    },
                    AuthorizationCodeReceived = (context) =>
                    {
                        ClientCredential credential   = new ClientCredential(ClientId, Password);
                        string tenantID               = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                        string signedInUserUniqueName = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value.Split('#')[context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value.Split('#').Length - 1];

                        var tokenCache = new ADALTokenCache(signedInUserUniqueName);
                        tokenCache.Clear();

                        AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantID), tokenCache);

                        //var items = authContext.TokenCache.ReadItems().ToList();

                        AuthenticationResult result1 = authContext.AcquireTokenByAuthorizationCode(
                            context.Code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential);

                        //items = authContext.TokenCache.ReadItems().ToList();

                        //AuthenticationResult result2 = authContext.AcquireTokenSilent(ConfigurationManager.AppSettings["ida:AzureResourceManagerIdentifier"], credential,
                        //    new UserIdentifier(signedInUserUniqueName, UserIdentifierType.RequiredDisplayableId));

                        //items = authContext.TokenCache.ReadItems().ToList();

                        return(Task.FromResult(0));
                    },
                    // we use this notification for injecting our custom logic
                    SecurityTokenValidated = (context) =>
                    {
                        // retriever caller data from the incoming principal
                        string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value;
                        if (!issuer.StartsWith("https://sts.windows.net/"))
                        {
                            // the caller is not from a trusted issuer - throw to block the authentication flow
                            throw new System.IdentityModel.Tokens.SecurityTokenValidationException();
                        }

                        return(Task.FromResult(0));
                    },
                    //AuthenticationFailed = (context) =>
                    //{
                    //    context.OwinContext.Response.Redirect(new UrlHelper(HttpContext.Current.Request.RequestContext).
                    //        Action("Index", "Home", null, HttpContext.Current.Request.Url.Scheme));
                    //    context.HandleResponse(); // Suppress the exception
                    //    return Task.FromResult(0);
                    //}
                }
            });
        }
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId  = SettingsHelper.ClientId,
                Authority = SettingsHelper.Authority,

                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // instead of using the default validation (validating against a single issuer value, as we do in line of business apps (single tenant apps)),
                    // we turn off validation
                    //
                    // NOTE:
                    // * In a multitenant scenario you can never validate against a fixed issuer string, as every tenant will send a different one.
                    // * If you don’t care about validating tenants, as is the case for apps giving access to 1st party resources, you just turn off validation.
                    // * If you do care about validating tenants, think of the case in which your app sells access to premium content and you want to limit access only to the tenant that paid a fee,
                    //       you still need to turn off the default validation but you do need to add logic that compares the incoming issuer to a list of tenants that paid you,
                    //       and block access if that’s not the case.
                    // * Refer to the following sample for a custom validation logic: https://github.com/AzureADSamples/WebApp-WebAPI-MultiTenant-OpenIdConnect-DotNet

                    ValidateIssuer = false
                },

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                    AuthorizationCodeReceived = (context) =>
                    {
                        var code = context.Code;

                        ClientCredential credential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.ClientSecret);
                        string tenantID             = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                        string signInUserId         = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                        AuthenticationContext authContext = new AuthenticationContext(
                            string.Format("{0}/{1}", SettingsHelper.AuthorizationUri, tenantID),
                            new ADALTokenCache(signInUserId));

                        // Get the access token for AAD Graph. Doing this will also initialize the token cache associated with the authentication context
                        // In theory, you could acquire token for any service your application has access to here so that you can initialize the token cache
                        AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                            code,
                            new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
                            credential,
                            SettingsHelper.AADGraphResourceId);

                        return(Task.FromResult(0));
                    },

                    RedirectToIdentityProvider = (context) =>
                    {
                        // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                        // this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
                        // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                        string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                        context.ProtocolMessage.RedirectUri           = appBaseUrl + "/";
                        context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;

                        return(Task.FromResult(0));
                    },

                    AuthenticationFailed = (context) =>
                    {
                        // Suppress the exception if you don't want to see the error
                        context.HandleResponse();
                        return(Task.FromResult(0));
                    }
                }
            });
        }
        //
        // This method will be invoked as a call-back from an authentication service (e.g., https://login.windows.net/).
        // It is not intended to be called directly, or to be called without first invoking the "GetAuthorizationUrl" method.
        // On completion, the method will cache the refresh token and access tokens, and redirect to the URL
        //     specified in the state cookie (created by the "GetAuthorizationUrl" method, with its unique ID
        //     included in the "state" of this method).
        //
        public ActionResult Index(string code, string error, string error_description, string resource, string state)
        {
            resource = GetFromCache("Resource").ToString();

            // NOTE: In production, OAuth must be done over a secure HTTPS connection.

            if (Request.Url.Scheme != "https" && !Request.Url.IsLoopback)
            {
                HandleErrorInfo errorViewModel = new HandleErrorInfo(new Exception("OAuth must use HTTPS"), "OAuth", "Index");
                return(View("Error", errorViewModel));
            }


            // Ensure there is a state value on the response.  If there is none, stop OAuth processing and display an error.

            if (state == null)
            {
                HandleErrorInfo errorViewModel = new HandleErrorInfo(new Exception("Anti-Forgery state value not found"), "OAuth", "Index");
                return(View("Error", errorViewModel));
            }


            // Ensure the saved state value matches the value from the response.  If it does not, stop OAuth processing and display an error.

            if (!FindOAuthStateInCache(state))
            {
                RemoveOAuthStateFromCache(state);
                HandleErrorInfo errorViewModel = new HandleErrorInfo(new Exception("Anti-Forgery state failed validation"), "OAuth", "Index");
                return(View("Error", errorViewModel));
            }

            RemoveOAuthStateFromCache(state);


            // Handle errors from the OAuth response, if any.  If there are errors, stop OAuth processing and display an error.

            if (error != null)
            {
                HandleErrorInfo errorViewModel = new HandleErrorInfo(new Exception(error), "OAuth", "Index");
                return(View("Error", errorViewModel));
            }


            // Redeem the authorization code from the response for an access token and refresh token.

            try
            {
                ClientCredential      credential  = new ClientCredential(clientId, appKey);
                string                authority   = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
                AuthenticationContext authContext = new AuthenticationContext(authority);
                AuthenticationResult  result      = authContext.AcquireTokenByAuthorizationCode(
                    code, new Uri(Request.Url.GetLeftPart(UriPartial.Path)), credential);

                // Cache the access token and refresh token
                SaveAccessTokenInCache(resource, result.AccessToken, (result.ExpiresOn.AddMinutes(-5)).ToString());
                SaveRefreshTokenInCache(result.RefreshToken);

                // Also save the Tenant ID for later use when calling the Graph API.
                SaveInCache("TenantId", result.TenantId);

                // Return to the originating page where the user triggered the sign-in
                Uri redirectTo = (Uri)GetFromCache("RedirectTo");
                return(Redirect(redirectTo.ToString()));
            }
            catch (Exception x)
            {
                HandleErrorInfo errorViewModel = new HandleErrorInfo(x, "OAuth", "Index");
                return(View("Error", errorViewModel));
            }
        }
        public void ConfigureAuth(IAppBuilder app)
        {
            var clientId    = Settings.ClientId;
            var redirectUri = Settings.RedirectUri;
            var authority   = Settings.Authority;

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(
                new CookieAuthenticationOptions
            {
                Provider = new CookieAuthenticationProvider
                {
                    OnResponseSignIn = context =>
                    {
                        var identitiy     = context.Identity;
                        var accessToken   = HttpContext.Current.Items[Settings.AccessTokenKey] as string;
                        var memberIdClaim = identitiy.FindFirst(Settings.ObjectIdentifierClaimType);
                        if (!string.IsNullOrWhiteSpace(accessToken) && memberIdClaim != null)
                        {
                            var memberId        = memberIdClaim.Value;
                            var graphConnection = CreateGraphConnection(accessToken);
                            if (graphConnection.IsMemberOf(Settings.UsersGroupId, memberId))
                            {
                                identitiy.AddClaim(new Claim(ClaimTypes.Role, Settings.UsersRole, ClaimValueTypes.String, Settings.RoleClaimIssuer));
                            }

                            if (graphConnection.IsMemberOf(Settings.AuditGroupId, memberId))
                            {
                                identitiy.AddClaim(new Claim(ClaimTypes.Role, Settings.AdminRole, ClaimValueTypes.String, Settings.RoleClaimIssuer));
                            }
                        }
                    }
                }
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId              = clientId,
                Authority             = authority,
                PostLogoutRedirectUri = redirectUri,
                Notifications         = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = context =>
                    {
                        var code            = context.Code;
                        var appKey          = Settings.Password;
                        var credential      = new ClientCredential(clientId, appKey);
                        var graphResourceId = Settings.GraphResourceID;
                        var authContext     = new AuthenticationContext(authority);

                        var result = authContext.AcquireTokenByAuthorizationCode(
                            code,
                            new Uri(redirectUri),
                            credential,
                            graphResourceId);

                        // Save the Azure AD access token in the context of the request.
                        HttpContext.Current.Items[Settings.AccessTokenKey] = result.AccessToken;

                        return(Task.FromResult(0));
                    }
                }
            });
        }
Пример #8
0
        public void ConfigureAuth(IAppBuilder app)
        {
            string ClientId           = ConfigurationManager.AppSettings["ida:ClientID"];
            string Password           = ConfigurationManager.AppSettings["ida:Password"];
            string Authority          = string.Format(ConfigurationManager.AppSettings["ida:Authority"], "common");
            string GraphAPIIdentifier = ConfigurationManager.AppSettings["ida:GraphAPIIdentifier"];

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions {
            });
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId  = ClientId,
                Authority = Authority,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,
                    // map the claimsPrincipal's roles to the roles claim
                    RoleClaimType = "roles",
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    RedirectToIdentityProvider = (context) =>
                    {
                        // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                        // this allows you to deploy your app (to Azure Web Sites, for example) without having to change settings
                        // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                        //string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                        context.ProtocolMessage.RedirectUri           = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path);
                        context.ProtocolMessage.PostLogoutRedirectUri = new UrlHelper(HttpContext.Current.Request.RequestContext).Action("Index", "Home", null, HttpContext.Current.Request.Url.Scheme);
                        context.ProtocolMessage.Resource = GraphAPIIdentifier;

                        return(Task.FromResult(0));
                    },
                    AuthorizationCodeReceived = (context) =>
                    {
                        ClientCredential credential = new ClientCredential(ClientId, Password);
                        string tenantID             = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                        string signedInUserID       = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                        AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantID), new ADALTokenCache(signedInUserID));
                        AuthenticationResult result       = authContext.AcquireTokenByAuthorizationCode(
                            context.Code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential);

                        if (GraphUtil.IsUserAADAdmin(context.AuthenticationTicket.Identity))
                        {
                            context.AuthenticationTicket.Identity.AddClaim(new Claim("roles", "admin"));
                        }

                        return(Task.FromResult(0));
                    },
                    // we use this notification for injecting our custom logic
                    SecurityTokenValidated = (context) =>
                    {
                        // retriever caller data from the incoming principal
                        string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value;
                        if (db.Organizations.FirstOrDefault(a => (a.Issuer == issuer)) == null)
                        {
                            // the caller is not from a trusted issuer - throw to block the authentication flow
                            throw new System.IdentityModel.Tokens.SecurityTokenValidationException();
                        }

                        return(Task.FromResult(0));
                    },
                    AuthenticationFailed = (context) =>
                    {
                        context.OwinContext.Response.Redirect(new UrlHelper(HttpContext.Current.Request.RequestContext).
                                                              Action("Index", "Home", null, HttpContext.Current.Request.Url.Scheme));
                        context.HandleResponse();     // Suppress the exception
                        return(Task.FromResult(0));
                    }
                }
            });
        }
Пример #9
0
        public void ConfigureAuth(IAppBuilder app)
        {
            app.MapSignalR();

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            var cookieAuthenticationOptions = new CookieAuthenticationOptions()
            {
                CookieName         = CookieName,
                ExpireTimeSpan     = TimeSpan.FromDays(30),
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                SlidingExpiration  = true,
            };

            app.UseCookieAuthentication(cookieAuthenticationOptions);

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId                  = SettingsHelper.ClientIdApp2,
                Authority                 = SettingsHelper.Authority,
                UseTokenLifetime          = false,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // instead of using the default validation (validating against a single issuer value, as we do in line of business apps (single tenant apps)),
                    // we turn off validation
                    //
                    // NOTE:
                    // * In a multitenant scenario you can never validate against a fixed issuer string, as every tenant will send a different one.
                    // * If you don’t care about validating tenants, as is the case for apps giving access to 1st party resources, you just turn off validation.
                    // * If you do care about validating tenants, think of the case in which your app sells access to premium content and you want to limit access only to the tenant that paid a fee,
                    //       you still need to turn off the default validation but you do need to add logic that compares the incoming issuer to a list of tenants that paid you,
                    //       and block access if that’s not the case.
                    // * Refer to the following sample for a custom validation logic: https://github.com/AzureADSamples/WebApp-WebAPI-MultiTenant-OpenIdConnect-DotNet

                    ValidateIssuer = false
                },

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                    AuthorizationCodeReceived = (context) =>
                    {
                        var code = context.Code;

                        string tenantID     = context.AuthenticationTicket.Identity.FindFirst(ExtendedClaimsType.TenantId).Value;
                        string userObjectId = context.AuthenticationTicket.Identity.FindFirst(ExtendedClaimsType.ObjectId).Value;
                        AuthenticationContext authContext = new AuthenticationContext(string.Format("{0}/{1}", SettingsHelper.AuthorizationUri, tenantID), new ADALTokenCache(userObjectId));

                        ClientCredential credential = SettingsHelper.GetApp2Credentials();
                        // Get the access token for AAD Graph. Doing this will also initialize the token cache associated with the authentication context
                        // In theory, you could acquire token for any service your application has access to here so that you can initialize the token cache
                        Uri redirectUri             = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
                        AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(code, redirectUri, credential, SettingsHelper.AADGraphResourceId);

                        return(Task.FromResult(0));
                    },

                    RedirectToIdentityProvider = (RedirectToIdentityProviderNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) =>
                    {
                        //If the call comes from web api and if the user is not authenticated, do not redirect returns a good old 401
                        string basePath = context.Request.Path.HasValue ? context.Request.Path.Value : null;
                        if (basePath != null && (basePath.StartsWith("/api") || basePath.StartsWith("/hangfire")))
                        {
                            context.HandleResponse();
                        }
                        else
                        {
                            string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                            if (context.Request.QueryString.HasValue && context.Request.QueryString.Value.StartsWith(AccountController.SignalRRefCst))
                            {
                                var nameValue = HttpUtility.ParseQueryString(context.Request.QueryString.Value);
                                string suffix = AccountController.GetCloseAutoParameters(nameValue[AccountController.SignalRRefCst]);
                                context.ProtocolMessage.RedirectUri           = appBaseUrl + SettingsHelper.PopupLoginRedirectRelativeUri + "?" + suffix;
                                context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl + SettingsHelper.PopupLoginRedirectRelativeUri + "?" + suffix;
                            }
                            else
                            {
                                context.ProtocolMessage.RedirectUri           = appBaseUrl + SettingsHelper.LoginLogoutRedictRelativeUri;
                                context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl + SettingsHelper.LoginLogoutRedictRelativeUri;
                            }
                        }

                        return(Task.FromResult(0));
                    },
                    AuthenticationFailed = (context) =>
                    {
                        // Suppress the exception if you don't want to see the error
                        context.HandleResponse();
                        return(Task.FromResult(0));
                    }
                }
            });
        }
        /// <summary>
        /// Configures application authentication.
        /// </summary>
        /// <param name="app">The application to configure.</param>
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions {
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId  = ApplicationConfiguration.ActiveDirectoryClientID,
                Authority = ApplicationConfiguration.ActiveDirectoryEndPoint + "common",
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // instead of using the default validation (validating against a single issuer value, as we do in line of business apps),
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    AuthorizationCodeReceived = async(context) =>
                    {
                        string userTenantId         = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                        string signedInUserObjectId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

                        // login to the user AD tenant
                        ClientCredential webPortalcredentials = new ClientCredential(ApplicationConfiguration.ActiveDirectoryClientID, ApplicationConfiguration.ActiveDirectoryClientSecret);
                        AuthenticationContext userAuthContext = new AuthenticationContext(ApplicationConfiguration.ActiveDirectoryEndPoint + userTenantId);
                        AuthenticationResult userAuthResult   = userAuthContext.AcquireTokenByAuthorizationCode(
                            context.Code,
                            new Uri(
                                HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
                            webPortalcredentials,
                            ApplicationConfiguration.ActiveDirectoryGraphEndPoint);

                        // acquire a graph token to manage the user tenant
                        Uri serviceRoot = new Uri(new Uri(ApplicationConfiguration.ActiveDirectoryGraphEndPoint), userTenantId);
                        ActiveDirectoryClient userAdClient = new ActiveDirectoryClient(serviceRoot, async() => await Task.FromResult(userAuthResult.AccessToken));

                        // add the user roles to the claims
                        var userMemberships = userAdClient.Users.GetByObjectId(signedInUserObjectId).MemberOf.ExecuteAsync().Result;

                        foreach (var membership in userMemberships.CurrentPage)
                        {
                            DirectoryRole role = membership as DirectoryRole;

                            if (role != null)
                            {
                                context.AuthenticationTicket.Identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, role.DisplayName));
                            }
                        }

                        if (userTenantId != ApplicationConfiguration.ActiveDirectoryTenantId)
                        {
                            string partnerCenterCustomerId = string.Empty;

                            try
                            {
                                // Check to see if this login came from the tenant of a customer of the partner
                                var customerDetails = ApplicationDomain.Instance.PartnerCenterClient.Customers.ById(userTenantId).Get();

                                // indeed a customer
                                partnerCenterCustomerId = customerDetails.Id;
                            }
                            catch (PartnerException readCustomerProblem)
                            {
                                if (readCustomerProblem.ErrorCategory == PartnerErrorCategory.NotFound)
                                {
                                    // this is not an exiting customer tenant, try to locate the user in the customers repository
                                    partnerCenterCustomerId = await ApplicationDomain.Instance.CustomersRepository.RetrieveAsync(userTenantId);
                                }
                                else
                                {
                                    throw;
                                }
                            }

                            if (!string.IsNullOrWhiteSpace(partnerCenterCustomerId))
                            {
                                // add the customer ID to the claims
                                context.AuthenticationTicket.Identity.AddClaim(new System.Security.Claims.Claim("PartnerCenterCustomerID", partnerCenterCustomerId));
                            }
                        }
                        else
                        {
                            if (context.AuthenticationTicket.Identity.FindFirst(System.Security.Claims.ClaimTypes.Role).Value != Startup.GlobalAdminUserRole)
                            {
                                // this login came from the partner's tenant, only allow admins to access the site, non admins will only
                                // see the unauthenticated experience but they can't configure the portal nor can purchase
                                Trace.TraceInformation("Blocked log in from non admin partner user: {0}", signedInUserObjectId);

                                throw new AuthorizationException(System.Net.HttpStatusCode.Unauthorized, Resources.NonAdminUnauthorizedMessage);
                            }
                        }
                    },
                    AuthenticationFailed = (context) =>
                    {
                        // redirect to the error page
                        context.OwinContext.Response.Redirect("/Home/Error?errorMessage=" + context.Exception.Message);
                        context.HandleResponse();
                        return(Task.FromResult(0));
                    }
                }
            });
        }
        public async Task <ActionResult> Complete(string code, string error, string error_description, string resource, string state)
        {
            using (var db = new TimesheetContext())
            {
                if (!String.IsNullOrEmpty(error) || !String.IsNullOrEmpty(error_description))
                {
                    return(View("RegistrationError", new RegistrationErrorModel()
                    {
                        Error = error, ErrorDescription = error_description
                    }));
                }

                var registrationRequest = await db.RegistrationRequests.FirstOrDefaultAsync(r => r.SignupToken == state);

                if (registrationRequest == null)
                {
                    return(View("RegistrationRequestUnknown"));
                }

                // Get the user's profile from Azure AD.
                var credential = new ClientCredential(ConfigurationManager.AppSettings["AzureAD:ClientID"],
                                                      ConfigurationManager.AppSettings["AzureAD:Key"]);
                var authContext = new AuthenticationContext("https://login.windows.net/common/");
                var result      = authContext.AcquireTokenByAuthorizationCode(code, new Uri(Request.Url.GetLeftPart(UriPartial.Path)), credential);

                // Clean up the registration request.
                db.RegistrationRequests.Remove(registrationRequest);

                // Prevent duplicate users.
                var userExists = await db.Users.AnyAsync(u => u.AzureTenantId == result.TenantId && u.AzureUpn == result.UserInfo.DisplayableId);

                if (!userExists)
                {
                    // Create the user.
                    var user = new User();
                    user.CreatedOn     = DateTime.UtcNow;
                    user.Id            = Guid.NewGuid();
                    user.Firstname     = result.UserInfo.GivenName;
                    user.Lastname      = result.UserInfo.FamilyName;
                    user.AzureTenantId = result.TenantId;
                    user.AzureUpn      = result.UserInfo.DisplayableId;
                    db.Users.Add(user);
                }

                // Consent happend by administrator for the whole organization..
                if (registrationRequest.AdminConsented)
                {
                    // Prevent duplicate tenants.
                    var directoryExists = await db.AzureDirectories.AnyAsync(u => u.TenantId == result.TenantId);

                    if (!directoryExists)
                    {
                        // Create the tenant.
                        var tenant = new AzureDirectory();
                        tenant.CreatedOn = DateTime.UtcNow;
                        tenant.Id        = Guid.NewGuid();
                        tenant.Issuer    = String.Format("https://sts.windows.net/{0}/", result.TenantId);
                        tenant.TenantId  = result.TenantId;
                        tenant.Name      = registrationRequest.OrganizationName;
                        db.AzureDirectories.Add(tenant);
                    }

                    // Save.
                    await db.SaveChangesAsync();

                    // Show confirmation page.
                    return(View("TenantRegistrationSuccess"));
                }

                // Save.
                await db.SaveChangesAsync();

                // Show user confirmation page.
                return(View("UserRegistrationSuccess"));
            }
        }
Пример #12
0
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId  = SettingsHelper.ClientId,
                Authority = SettingsHelper.Authority,

                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuer = false
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                    AuthorizationCodeReceived = (context) =>
                    {
                        var code = context.Code;

                        ClientCredential credential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.ClientSecret);
                        string tenantID             = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                        string signInUserId         = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                        AuthenticationContext authContext = new AuthenticationContext(string.Format("{0}/{1}", SettingsHelper.AuthorizationUri, tenantID), null);    // new ADALTokenCache(signInUserId));

                        // Get the access token for AAD Graph. Doing this will also initialize the token cache associated with the authentication context
                        // In theory, you could acquire token for any service your application has access to here so that you can initialize the token cache
                        AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, SettingsHelper.AADGraphResourceId);

                        //cache the appropriate settings in session state
                        HttpContext.Current.Session.Add("TenantID", tenantID);
                        HttpContext.Current.Session.Add("RefreshToken", result.RefreshToken);

                        return(Task.FromResult(0));
                    },

                    RedirectToIdentityProvider = (context) =>
                    {
                        // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                        // this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
                        // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                        string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                        context.ProtocolMessage.RedirectUri           = appBaseUrl + "/";
                        context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;

                        return(Task.FromResult(0));
                    },

                    AuthenticationFailed = (context) =>
                    {
                        // Suppress the exception if you don't want to see the error
                        context.HandleResponse();
                        return(Task.FromResult(0));
                    }
                }
            });
        }