private static UserInfo GetOrCreateCachedUserInfo(JwtSecurityToken jwt, PortalSettings portalSettings, System.Security.Claims.Claim userClaim)
        {
            var usernamePrefixEnabled = bool.Parse(AzureConfig.GetSetting(AzureConfig.ServiceName, "UsernamePrefixEnabled", portalSettings.PortalId, "true"));
            var usernameToFind        = usernamePrefixEnabled ? $"azure-{userClaim.Value}" : userClaim.Value;
            var userInfo = UserController.GetUserByName(portalSettings.PortalId, usernameToFind);
            var tokenKey = ComputeSha256Hash(jwt.RawData);
            var cache    = DotNetNuke.Services.Cache.CachingProvider.Instance();

            if (string.IsNullOrEmpty((string)cache.GetItem($"SyncAADToken|{tokenKey}")))
            {
                var azureClient = new AzureClient(portalSettings.PortalId, AuthMode.Login)
                {
                    JwtIdToken = jwt
                };
                azureClient.SetAuthTokenInternal(jwt.RawData);
                azureClient.SetAutoMatchExistingUsers(true);
                var userData = azureClient.GetCurrentUserInternal(jwt);
                if (userInfo == null)
                {
                    // If user doesn't exist, create the user
                    userInfo                     = userData.ToUserInfo(usernamePrefixEnabled);
                    userInfo.PortalID            = portalSettings.PortalId;
                    userInfo.Membership.Password = UserController.GeneratePassword();
                    var result = UserController.CreateUser(ref userInfo);
                }

                azureClient.AuthenticateUser(userData, portalSettings, HttpContext.Current.Request["REMOTE_ADDR"], azureClient.AddCustomProperties, azureClient.OnUserAuthenticated);
                azureClient.UpdateUserProfile(jwt, false, false);
                cache.Insert($"SyncAADToken|{tokenKey}", "OK", null, jwt.ValidTo, TimeSpan.Zero);
            }

            return(userInfo);
        }
        public static void UpdateConfig(AzureConfig config)
        {
            HostController.Instance.Update(config.Service + "_UseGlobalSettings", config.UseGlobalSettings.ToString(),
                                           true);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_ApiKey", config.APIKey);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_ApiSecret", config.APISecret);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_RedirectUri", config.RedirectUri);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_TenantId", config.TenantId);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_AutoRedirect", config.AutoRedirect.ToString());
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_Enabled", config.Enabled.ToString());
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_AADApplicationId", config.AADApplicationId);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_AADApplicationKey", config.AADApplicationKey);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_JwtAudiences", config.JwtAudiences);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_RoleSyncEnabled", config.RoleSyncEnabled.ToString());
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_ProfileSyncEnabled", config.ProfileSyncEnabled.ToString());
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_JwtAuthEnabled", config.JwtAuthEnabled.ToString());
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_APIResource", config.APIResource);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_Scopes", config.Scopes);
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_UsernamePrefixEnabled", config.UsernamePrefixEnabled.ToString());
            UpdateScopedSetting(config.UseGlobalSettings, config.PortalID, config.Service + "_GroupNamePrefixEnabled", config.GroupNamePrefixEnabled.ToString());

            UpdateConfig((OAuthConfigBase)config);

            // Clear config after update
            DataCache.RemoveCache(GetCacheKey(config.Service, config.PortalID));
        }
        public static void UpdateConfig(AzureConfig config)
        {
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_AppIdUri", config.AppIdUri);
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_TokenEndpoint", config.TokenEndpoint);
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_AuthorizationEndpoint", config.AuthorizationEndpoint);
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_GraphEndpoint", config.GraphEndpoint);

            UpdateConfig((OAuthConfigBase)config);
        }
Example #4
0
        public static void UpdateConfig(AzureConfig config)
        {
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_ApiKey", config.APIKey);
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_ApiSecret", config.APISecret);
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_TenantId", config.TenantId);
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_AutoRedirect", config.AutoRedirect.ToString());
            PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_Enabled", config.Enabled.ToString());

            UpdateConfig((OAuthConfigBase)config);
        }
 internal static OpenIdConnectConfiguration GetConfig(int portalId, AzureConfig azureConfig)
 {
     if (!Config.ContainsKey(portalId))
     {
         var tokenConfigurationUrl = $"https://login.microsoftonline.com/{azureConfig.TenantId}/.well-known/openid-configuration";
         var _configManager        = new ConfigurationManager <OpenIdConnectConfiguration>(tokenConfigurationUrl, new OpenIdConnectConfigurationRetriever());
         var _config = _configManager.GetConfigurationAsync().Result;
         Config.Add(portalId, _config);
     }
     return(Config[portalId]);
 }
        public new static AzureConfig GetConfig(string service, int portalId)
        {
            string key    = GetCacheKey(service, portalId);
            var    config = (AzureConfig)DataCache.GetCache(key);

            if (config == null)
            {
                config = new AzureConfig(service, portalId);
                DataCache.SetCache(key, config);
            }
            return(config);
        }
Example #7
0
        public AzureClient(int portalId, AuthMode mode)
            : base(portalId, mode, AzureConfig.ServiceName)
        {
            Settings = new AzureConfig(AzureConfig.ServiceName, portalId);

            TokenMethod = HttpMethod.POST;


            if (!string.IsNullOrEmpty(Settings.TenantId))
            {
                TokenEndpoint         = new Uri(string.Format(Utils.GetAppSetting("AzureAD.TokenEndpointPattern", TokenEndpointPattern), Settings.TenantId));
                LogoutEndpoint        = new Uri(string.Format(Utils.GetAppSetting("AzureAD.LogoutEndpointPattern", LogoutEndpointPattern), Settings.TenantId, UrlEncode(HttpContext.Current.Request.Url.ToString())));
                AuthorizationEndpoint = new Uri(string.Format(Utils.GetAppSetting("AzureAD.AuthorizationEndpointPattern", AuthorizationEndpointPattern), Settings.TenantId));
                MeGraphEndpoint       = new Uri(string.Format(Utils.GetAppSetting("AzureAD.GraphEndpointPattern", GraphEndpointPattern), Settings.TenantId));
            }

            if (string.IsNullOrEmpty(Settings.APIResource) && string.IsNullOrEmpty(Settings.Scopes))
            {
                Scope       = DefaultScopes;
                APIResource = "";
            }
            else
            {
                Scope = string.Join(" ", Settings.Scopes
                                    .Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries)
                                    .Select(x => $"{Settings.APIResource}{x.Trim()}"));
                APIResource = Settings.APIResource;
            }

            if (!string.IsNullOrEmpty(Settings.RedirectUri))
            {
                CallbackUri = new Uri(Settings.RedirectUri);
            }

            APIKey          = Settings.APIKey;
            APISecret       = Settings.APISecret;
            AuthTokenName   = "AzureUserToken";
            OAuthVersion    = "2.0";
            OAuthHeaderCode = "Basic";
            LoadTokenCookie(string.Empty);
            JwtIdToken = null;

            _prefixServiceToUserName  = Settings.UsernamePrefixEnabled;
            _prefixServiceToGroupName = Settings.GroupNamePrefixEnabled;
        }
        public AzureClient(int portalId, AuthMode mode)
            : base(portalId, mode, "Azure")
        {
            var config = new AzureConfig("Azure", portalId);

            TokenMethod           = HttpMethod.POST;
            TokenEndpoint         = new Uri(config.TokenEndpoint);
            AuthorizationEndpoint = new Uri(config.AuthorizationEndpoint);
            MeGraphEndpoint       = new Uri(config.GraphEndpoint);

            Scope = "email";

            AuthTokenName = "AzureUserToken";
            APIResource   = config.AppIdUri;
            OAuthVersion  = "2.0";
            LoadTokenCookie(String.Empty);
            JwtSecurityToken = null;
        }
        public AzureClient(int portalId, AuthMode mode)
            : base(portalId, mode, "Azure")
        {
            var config = new AzureConfig("Azure", portalId);

            TokenMethod = HttpMethod.POST;


            if (!string.IsNullOrEmpty(config.TenantId))
            {
                TokenEndpoint         = new Uri(string.Format(Utils.GetAppSetting("AzureAD.TokenEndpointPattern", TokenEndpointPattern), config.TenantId));
                LogoutEndpoint        = new Uri(string.Format(Utils.GetAppSetting("AzureAD.LogoutEndpointPattern", LogoutEndpointPattern), config.TenantId, UrlEncode(HttpContext.Current.Request.Url.ToString())));
                AuthorizationEndpoint = new Uri(string.Format(Utils.GetAppSetting("AzureAD.AuthorizationEndpointPattern", AuthorizationEndpointPattern), config.TenantId));
                MeGraphEndpoint       = new Uri(string.Format(Utils.GetAppSetting("AzureAD.GraphEndpointPattern", GraphEndpointPattern), config.TenantId));
            }

            Scope = "email";

            AuthTokenName = "AzureUserToken";
            APIResource   = config.APIKey;
            OAuthVersion  = "2.0";
            LoadTokenCookie(string.Empty);
            JwtSecurityToken = null;
        }
Example #10
0
        public override void AuthenticateUser(UserData user, PortalSettings settings, string IPAddress, Action <NameValueCollection> addCustomProperties, Action <UserAuthenticatedEventArgs> onAuthenticated)
        {
            var portalSettings = settings;

            if (IsCurrentUserAuthorized() && JwtIdToken != null)
            {
                // Check if portalId profile mapping exists
                var portalUserMapping = UserMappingsRepository.Instance.GetUserMapping("PortalId", GetCalculatedPortalId());
                if (!string.IsNullOrEmpty(portalUserMapping?.AadClaimName))
                {
                    var claimName = portalUserMapping?.AadClaimName;
                    // Get PortalId from claim
                    var portalIdClaim = JwtIdToken.Claims.FirstOrDefault(x => x.Type == claimName)?.Value;
                    if (string.IsNullOrEmpty(portalIdClaim))
                    {
                        throw new SecurityTokenException("The user has no portalId claim and portalId profile mapping is setup. The AAD user can't login to any portal until the portalId attribute has been setup for the user. Ensure that the PortalId claim has been setup and included on the policy being used.");
                    }
                    if (int.TryParse(portalIdClaim, out int portalId) && portalId != portalSettings.PortalId)
                    {
                        // Redirect to the user portal
                        var request = HttpContext.Current.Request;
                        if (!string.IsNullOrEmpty(request.Headers["Authorization"]) && request.Headers["Authorization"].StartsWith("Bearer"))
                        {
                            throw new SecurityTokenException($"The user portalId claim ({portalId}) is different from current portalId ({portalSettings.PortalId}). Portal redirection flow is not supported on native apps. Please call the API from the corresponding portal URL");
                        }
                        var state = new State(request["state"]);
                        HttpContext.Current.Response.Redirect(Utils.GetLoginUrl(portalId, state.Culture, request));
                        return;
                    }
                }
            }

            var userIdClaim = Utils.GetUserIdClaim(GetCalculatedPortalId());
            var userClaim   = JwtIdToken.Claims.FirstOrDefault(x => x.Type == userIdClaim);

            if (userClaim == null)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Error($"Can't find '{userIdClaim}' claim on token");
                }
                throw new MissingFieldException($"Can't find '{userIdClaim}' claim on token, needed to identify the user");
            }

            var usernamePrefixEnabled = bool.Parse(AzureConfig.GetSetting(AzureConfig.ServiceName, "UsernamePrefixEnabled", portalSettings.PortalId, "true"));
            var usernameToFind        = usernamePrefixEnabled ? $"azure-{userClaim.Value}" : userClaim.Value;
            var userInfo = UserController.GetUserByName(portalSettings.PortalId, usernameToFind);

            // If user doesn't exist on current portal, AuthenticateUser() will create it.
            // Otherwise, AuthenticateUser will perform a Response.Redirect, so we have to sinchronize the roles before that, to avoid the ThreadAbortException caused by the Response.Redirect
            if (userInfo == null)
            {
                base.AuthenticateUser(user, portalSettings, IPAddress, addCustomProperties, onAuthenticated);
                if (IsCurrentUserAuthorized())
                {
                    userInfo = UserController.GetUserByName(portalSettings.PortalId, usernameToFind);
                    if (userInfo == null)
                    {
                        throw new SecurityTokenException($"The logged in user {usernameToFind} does not belong to PortalId {portalSettings.PortalId}");
                    }
                    UpdateUserAndRoles(userInfo);
                    MarkUserAsAad(userInfo);
                }
            }
            else
            {
                if (IsCurrentUserAuthorized())
                {
                    UpdateUserAndRoles(userInfo);
                }
                base.AuthenticateUser(user, portalSettings, IPAddress, addCustomProperties, onAuthenticated);
            }
        }
        private static JwtSecurityToken GetAndValidateJwt(string rawToken, bool checkExpiry)
        {
            JwtSecurityToken jwt;

            try
            {
                jwt = new JwtSecurityToken(rawToken);
            }
            catch (Exception ex)
            {
                Logger.Error("Unable to construct JWT object from authorization value. " + ex.Message);
                return(null);
            }

            if (checkExpiry)
            {
                var now = DateTime.UtcNow;
                if (now < jwt.ValidFrom.AddMinutes(-5) || now > jwt.ValidTo)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug("Token is expired");
                    }
                    return(null);
                }
            }

            var portalSettings = PortalController.Instance.GetCurrentPortalSettings();
            var azureConfig    = new AzureConfig(AzureConfig.ServiceName, portalSettings.PortalId);

            if (portalSettings == null)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug("Unable to retrieve portal settings");
                }
                return(null);
            }
            if (!azureConfig.Enabled || !azureConfig.JwtAuthEnabled)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug($"Azure AD JWT auth is not enabled for portal {portalSettings.PortalId}");
                }
                return(null);
            }

            var _config        = GetConfig(portalSettings.PortalId, azureConfig);
            var validAudiences = azureConfig.JwtAudiences.Split(',').Select(x => x.Trim()).Where(x => !string.IsNullOrEmpty(x)).ToArray();

            if (validAudiences.Length == 0)
            {
                validAudiences = new[] { azureConfig.APIKey };
            }

            try
            {
                // Validate token.
                var _tokenValidator      = new JwtSecurityTokenHandler();
                var validationParameters = new TokenValidationParameters
                {
                    // App Id URI and AppId of this service application are both valid audiences.
                    ValidAudiences = validAudiences,
                    // Support Azure AD V1 and V2 endpoints.
                    ValidIssuers      = new[] { _config.Issuer, $"{_config.Issuer}v2.0/" },
                    IssuerSigningKeys = _config.SigningKeys
                };

                var claimsPrincipal = _tokenValidator.ValidateToken(rawToken, validationParameters, out SecurityToken _);
            }
            catch (Exception ex)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug($"Error validating token: {ex}");
                }
                return(null);
            }

            return(jwt);
        }
        private UserInfo TryGetUser(JwtSecurityToken jwt)
        {
            try
            {
                var portalSettings = PortalController.Instance.GetCurrentPortalSettings();
                var azureConfig    = new AzureConfig(AzureConfig.ServiceName, portalSettings.PortalId);
                if (portalSettings == null)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug("Unable to retrieve portal settings");
                    }
                    return(null);
                }
                if (!azureConfig.Enabled || !azureConfig.JwtAuthEnabled)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug($"Azure AD JWT auth is not enabled for portal {portalSettings.PortalId}");
                    }
                    return(null);
                }

                var userIdClaim = Utils.GetUserIdClaim(azureConfig.UseGlobalSettings ? -1 : portalSettings.PortalId);
                var userClaim   = jwt.Claims.FirstOrDefault(x => x.Type == userIdClaim);
                if (userClaim == null)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug($"Can't find '{userIdClaim}' claim on token");
                    }
                }

                var userInfo = GetOrCreateCachedUserInfo(jwt, portalSettings, userClaim);
                if (userInfo == null)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug("Invalid user");
                    }
                    return(null);
                }

                var status = UserController.ValidateUser(userInfo, portalSettings.PortalId, false);
                var valid  =
                    status == UserValidStatus.VALID ||
                    status == UserValidStatus.UPDATEPROFILE ||
                    status == UserValidStatus.UPDATEPASSWORD;

                if (!valid && Logger.IsDebugEnabled)
                {
                    Logger.Debug("Inactive user status: " + status);
                    return(null);
                }

                return(userInfo);
            }
            catch (Exception ex)
            {
                Logger.Error("Error while login in: " + ex.Message);
            }
            return(null);
        }