Example #1
0
        public static async Task <bool> Create(ISEConnection connection, GuestUserViewModel user)
        {
            if (user.GuestAccessInfo == null)
            {
                throw new ArgumentNullException("GuestAccessInfo");
            }
            if (user.GuestInfo == null)
            {
                throw new ArgumentNullException("GuestInfo");
            }

            if (user.GuestAccessInfo.ValidDays < 1)
            {
                throw new IndexOutOfRangeException("ValidDays must be 1 or greater");
            }

            if (!user.GuestAccessInfo.FromDate.HasValue && user.GuestAccessInfo.ToDate.HasValue)
            {
                throw new ArgumentException("fromDate not set, but toDate is", "FromDate");
            }

            if (!user.GuestAccessInfo.FromDate.HasValue)
            {
                user.GuestAccessInfo.FromDate = DateTime.Now;
            }

            // TODO - Figure out how to make 1 day happen
            if (!user.GuestAccessInfo.ToDate.HasValue)
            {
                user.GuestAccessInfo.ToDate = user.GuestAccessInfo.FromDate.Value.AddDays(user.GuestAccessInfo.ValidDays - 1);
            }

            // Adjust local time to server time (currently, we assume UTC)
            // TODO : Fetch time zone information from the ISE server
            user.GuestAccessInfo.FromDate = user.GuestAccessInfo.FromDate.Value.ToUniversalTime();
            user.GuestAccessInfo.ToDate   = user.GuestAccessInfo.ToDate.Value.ToUniversalTime();

            return(await connection.RestPost(
                       "config/guestuser",
                       HttpStatusCode.Created,
                       new
            {
                GuestUser = user
            }
                       ));
        }
Example #2
0
 public GuestsPageUser()
 {
     InitializeComponent();
     BindingContext = guestUserViewModel = new GuestUserViewModel();
     Run();
 }
Example #3
0
        public async Task <ActionResult> SSOService()
        {
            var logger = log4net.LogManager.GetLogger("SAMLController");

            logger.Info("SSOService() - Single sign-on service entered");

            var pendingSessionKey = Session[ssoPendingSessionKey];

            logger.Debug("Session[ssoPendingSessionKey] = " + ((pendingSessionKey == null) ? "null" : pendingSessionKey.ToString()));

            // Either an authn request has been received or login has just completed in response to a previous authn request.
            // The SSO pending session flag is false if an authn request is expected. Otherwise, it is true if
            // a login has just completed and control is being returned to this page.
            bool ssoPending = pendingSessionKey != null && (bool)Session[ssoPendingSessionKey] == true;

            logger.Debug("ssoPending = " + ssoPending.ToString());
            logger.Debug("User.Identity.IsAuthenticated = " + User.Identity.IsAuthenticated.ToString());
            if (!(ssoPending && User.Identity.IsAuthenticated))
            {
                string partnerSP = null;

                // Receive the authn request from the service provider (SP-initiated SSO).
                SAMLIdentityProvider.ReceiveSSO(Request, out partnerSP);
                logger.Debug("partnerSP = " + partnerSP);

                // If the user isn't logged in at the identity provider, force the user to login.
                if (!User.Identity.IsAuthenticated)
                {
                    Session[ssoPendingSessionKey] = true;
                    logger.Info("User not authenticated, redirecting to login page()");

                    FormsAuthentication.RedirectToLoginPage();
                    return(new EmptyResult());
                }
            }

            Session[ssoPendingSessionKey] = null;

            // The user is logged in at the identity provider.
            // Respond to the authn request by sending a SAML response containing a SAML assertion to the SP.
            // Use the configured or logged in user name as the user name to send to the service provider (SP).
            // Include some user attributes.
            var userName = WebConfigurationManager.AppSettings[AppSettings.SubjectName];

            var identity = (ClaimsIdentity)User.Identity;

            if (string.IsNullOrEmpty(userName))
            {
                var bid = identity.FindFirst("bid_id");
                if (bid == null)
                {
                    logger.Info("bid_id claim not found, redirecting to login page");
                    FormsAuthentication.RedirectToLoginPage();
                    return(new EmptyResult());
                }

                userName = bid.Value;

                var firstName = identity.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname");
                var lastName  = identity.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname");

                logger.Info("Username obtained from BankID : " + userName);
                logger.Info("Firstname from BankID : " + ((firstName == null) ? "<not provided>" : firstName.Value));
                logger.Info("Lastname from BankID : " + ((lastName == null) ? "<not provided>" : lastName.Value));

                var iseSettings = Utility.Configuration.Settings.IseServer;

                var iseUri = new UriBuilder("https", iseSettings.ServerIP.ToString(), 9060);

                var developerConnection = new CiscoISE.ISEConnection(iseUri.Uri, iseSettings.ApiUsername, iseSettings.ApiPassword);

                var portals = await CiscoISE.Portals.Get(developerConnection);

                if (portals == null)
                {
                    throw new Exception("Could not access ISE to enumerate portals");
                }

                logger.Debug("Retrieved portals from the Cisco ISE server using the API account");

                // TODO : Research whether this is the best way to get the sponsor portal.
                var sponsorPortal = portals.Where(x => x.Name == "Sponsor Portal (default)").FirstOrDefault();
                if (sponsorPortal == null)
                {
                    throw new Exception("Could not access ISE to find GUID for Sponsor Portal (default)");
                }

                logger.Debug("Sponsor portal found on ISE server : " + sponsorPortal.Name);

                var sponsorConnection = new CiscoISE.ISEConnection(iseUri.Uri, iseSettings.SponsorPortalUsername, iseSettings.SponsorPortalPassword);

                logger.Debug("Finding an existing guest user with username : "******"Retrieved user " + userName + " from ISE server\n" + JsonConvert.SerializeObject(guestUser));
                }
                else
                {
                    logger.Info("Existing user (" + userName + ") not found, attempt to create a new one");

                    logger.Debug("Getting GuestTypes from ISE server");
                    // TODO : Catch errors on connecting to the API
                    var guestTypes = await CiscoISE.GuestTypes.Get(developerConnection);

                    if (guestTypes == null)
                    {
                        // TODO : Provide a better method of handling API issues
                        throw new Exception("Failed to get a list of GuestTypes from Cisco ISE");
                    }

                    // TODO : Provide a configuration option to allow specific guest types to be
                    //          chosen based on how the user is logging in.
                    var guestType = guestTypes.FirstOrDefault();
                    if (guestType == null)
                    {
                        // TODO : Provide a better method of dealing with there not being any guest types
                        throw new Exception("There appears to be no guest types configured in Cisco ISE");
                    }

                    logger.Info("Using first guest type in the list : " + guestType.Name);

                    logger.Debug("Getting list of guest locations from the ISE server");
                    // TODO : Catch exceptions on guest locations
                    var guestLocations = await CiscoISE.GuestLocations.Get(developerConnection);

                    if (guestLocations == null)
                    {
                        // TODO : Provide a better method of handling API issues
                        throw new Exception("Failed to obtain a list of guest locations from Cisco ISE");
                    }

                    // TODO : Provide a configuration option to allow specific guest locations to be
                    //         chosen based on where the user is logging in
                    var guestLocation = guestLocations.FirstOrDefault();
                    if (guestLocation == null)
                    {
                        // TODO : Provide a better method of handling API issues
                        throw new Exception("ISE does not appear to have any guest locations configured");
                    }

                    logger.Info("Using first guest location from the list " + guestLocation.Name);

                    //var randomPassword = Membership.GeneratePassword(16, 4);
                    var randomPassword = CiscoISE.Utility.PasswordGenerator.GenerateStrongGuestPassword();

                    // TODO : Consider removing this from the code. Though, the password is not used anywhere, it could be a "alarm" during a code audit
                    logger.Info("Automatically generated a password for the new user (" + randomPassword + ")");

                    // TODO : Add configuration settings to specify the duration which a guest account is valid
                    var validFrom  = DateTime.Now;
                    var validUntil = validFrom.AddHours(4);

                    guestUser = new GuestUserViewModel
                    {
                        GuestType = guestType.Name, // TODO : File "bug" with Cisco over name referencing instead of ID
                        PortalId  = sponsorPortal.Id.ToString(),
                        GuestInfo = new CiscoISE.GuestInfoViewModel
                        {
                            Username  = userName,
                            Password  = randomPassword,
                            FirstName = firstName == null ? "<unknown>" : firstName.Value,
                            LastName  = lastName == null ? "<unknown>" : lastName.Value,
                            Enabled   = true
                        },
                        GuestAccessInfo = new GuestAccessInfoViewModel
                        {
                            ValidDays = 1,
                            FromDate  = validFrom,
                            ToDate    = validUntil,
                            Location  = guestLocation.Name // TODO : File "bug" with Cisco over name reference instead of ID
                        }
                    };
                    logger.Debug("guestUser = "******"Creating new guest user");
                    var created = await CiscoISE.GuestUsers.Create(
                        sponsorConnection,
                        guestUser
                        );

                    logger.Info(created ? "Guest user created" : "Guest user failed to be created");
                    if (!created)
                    {
                        throw new Exception("Failed to create new guest user, cannot continue login process");
                    }
                }
            }

            var ClaimToAttributes = new []
            {
                new {
                    claimType         = Microsoft.IdentityModel.Protocols.OpenIdConnectParameterNames.AccessToken,
                    samlAttributeName = "bidAccessToken"
                },
                new {
                    claimType         = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth",
                    samlAttributeName = "dateofbirth"
                },
                new {
                    claimType         = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
                    samlAttributeName = "givenname"
                },
                new {
                    claimType         = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
                    samlAttributeName = "surname"
                },
                new {
                    claimType         = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
                    samlAttributeName = "name"
                }
            };

            logger.Info("Appending attributes to SAML assertion");
            var samlAttributes = new List <SAMLAttribute>();

            foreach (var claimToAttribute in ClaimToAttributes)
            {
                var claim = identity.FindFirst(claimToAttribute.claimType);
                if (claim != null)
                {
                    var attribute = new SAMLAttribute(
                        claimToAttribute.samlAttributeName,
                        SAMLIdentifiers.AttributeNameFormats.Unspecified,
                        null,
                        "xs:string",
                        claim.Value
                        );

                    samlAttributes.Add(attribute);
                }
            }

            ComponentSpace.SAML2.SAMLController.TraceLevel = System.Diagnostics.TraceLevel.Verbose;
            logger.Info("Sending SSO to SAML service provider");
            SAMLIdentityProvider.SendSSO(Response, userName, samlAttributes.ToArray());

            return(new EmptyResult());
        }