public override void DoLogin(RmUnifyUser user, DateTime maxSessionEnd, string returnUrl)
        {
            // Create our own cookie so we can insert DisplayName (because we want to use it on every page)
            // and make sure session length is appropriate.
            // If we didn't need this, we could just use FormsAuthentication.SetAuthCookie(user.Id, false)

            // Calculate session expiry as minimum of our app policy and that provided by RM Unify
            DateTime endTime = DateTime.Now.Add(FormsAuthentication.Timeout);
            if (endTime > maxSessionEnd)
            {
                endTime = maxSessionEnd;
            }
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2,
                user.Id,
                DateTime.Now,
                endTime,
                false,
                user.DisplayName,
                FormsAuthentication.FormsCookiePath);
            string encTicket = FormsAuthentication.Encrypt(ticket);
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
            cookie.HttpOnly = true;

            // If your website is entirely https, it is good practise to mark the cookie as secure
            // cookie.Secure = true;
            HttpContext.Current.Response.Cookies.Add(cookie);

            HttpContext.Current.Response.Redirect(returnUrl == null ? "/" : returnUrl);
        }
        /// <summary>
        /// Create a new organization or update an existing one.
        /// This method will never be called if the organization.Id is null (for example, if the attribute
        /// has not been requested from RM Unify).
        /// If your app stores information about an organization, it should use organization.Id as a key to create a
        /// new organization record or update an existing one.
        /// </summary>
        /// <param name="organization">Organization profile</param>
        /// <param name="source">Source of update (sign on or provisioning)</param>
        public override void CreateOrUpdateUser(RmUnifyUser rmUser, Source source)
        {
            /// This override supports giving each user a login name that is suitable for display
            if (_school == null)
            {
                throw new Exception("CreateOrUpdateUser() called before CreateOrUpdateOrganization()");
            }

            using (var context = new Context())
            {
                Account account = (from a in context.Accounts
                                   where a.RmUnifyId == rmUser.Id
                                   select a).SingleOrDefault();
                if (account == null)
                {
                    account = new Account()
                    {
                        RmUnifyId = rmUser.Id,
                        SchoolId = _school.Id,
                        Password = Guid.NewGuid().ToString() // use random unguessable password
                    };
                    context.Accounts.Add(account);
                }
                else
                {
                    if (account.SchoolId != _school.Id)
                    {
                        // If you use rmUnifyUser.PersonId, you will need to support a user moving between schools
                        // If you use rmUnifyUser.Id, a user moving between schools will be assigned a new Id
                        throw new Exception("School moves not supported");
                    }
                }

                account.LoginName = DeDupeLoginName(rmUser.UnifyUserName, rmUser.Id);
                account.DisplayName = rmUser.DisplayName;
                account.RoleEnum = GetRole(rmUser);
                account.DeletedDate = null;  // if previously deleted, restore
                if (source == Source.SingleSignOn)
                {
                    account.LastLogin = DateTime.Now;
                }
                context.SaveChanges();

                // Cache account for next method
                _account = account;
            }

            // Purge any old users from the system
            // In this example, we've chosen to implement this in the login process
            // If this is likely to be long running, we might want to implement it as a background task
            PurgeUsers();
        }
        /// <summary>
        /// Create or update a user in the application
        /// In this example, we want to store some custom data about the user (display name, last login and deleted date).
        /// Last login and deleted date allow us to soft delete users who haven't logged in for 3 months and then purge
        /// them after 1 year.
        /// We've implement the custom data by just extending the account model and going direct to the database to read
        /// and write the data; we could have equally created a custom membership user
        /// (http://msdn.microsoft.com/en-us/library/ms366730.aspx).
        /// </summary>
        /// <param name="rmUser">RM Unify user</param>
        /// <param name="source">Source of user information (always SingleSignOn at the moment)</param>
        public override void CreateOrUpdateUser(RmUnifyUser rmUser, Source source)
        {
            // Update the data associated with the user
            CreateOrUpdateUserData(rmUser);

            // Update the roles associated with the user
            CreateOrUpdateUserRoles(rmUser);

            // Purge any old users from the system
            // In this example, we've chosen to implement this in the login process
            // If this is likely to be long running, we might want to implement it as a background task
            PurgeUsers();
        }
        /// <summary>
        /// Log in as a pre-existing user who has been linked to an RM Unify user.
        /// This method is called when single sign on from RM Unify successfully completes.  CreateOrUpdateOrganization()
        /// and CreateOrUpdateUser() will always be called first (in that order) provided the appropriate Ids are available.
        /// Your app should set any session cookies required to log the user in.
        /// Your app should then redirect the user to returnUrl (if set) or to the default URL for this user in your app.
        /// </summary>
        /// <param name="appUserId">User ID in your app (typically login name)</param>
        /// <param name="appEstablishmentKey">App establishment key (as provided by you to the organization)</param>
        /// <param name="user">User profile</param>
        /// <param name="maxSessionEnd">Maxiumum time after which reauthentication should be prompted</param>
        /// <param name="returnUrl">Return URL specified in login request (null if none)</param>
        public override void DoLoginForLinkedUser(string appUserId, string appEstablishmentKey, RmUnifyUser user, DateTime maxSessionEnd, string returnUrl)
        {
            if (_account == null)
            {
                throw new Exception("DoLoginForLinkedUser() called before UpdateLinkedUser()");
            }

            if (_account.SchoolId != _school.Id)
            {
                throw new RmUnifySsoException(RmUnifySsoException.ERRORCODES_APPUSERIDNOTINESTABLISHMENT, "User " + appUserId + " is not in school with establishment key " + appEstablishmentKey);
            }

            // Can just call RmUnify.DoLogin() because the user to login as is already stored in _account
            DoLogin(user, maxSessionEnd, returnUrl);
        }
 /// <summary>
 /// Update properties of a pre-existing user that has been linked to RM Unify.
 /// Only necessary if your app supports the RM Unify user account matching process
 /// (http://dev.rmunify.com/reference/supporting-user-account-matching/the-rm-unify-process.aspx).
 /// In this case, the organization has provisioned users into your app outside RM Unify and wishes to connect RM Unify
 /// to their existing users. Their "app establishment key" and the existing user id in your app (typically login name)
 /// is passed in to this method so that you can verify that the user is in the establishment and update them.
 /// Called instead of CreateOrUpdateUser() if the current user has been linked to a user in your app as part of the
 /// RM Unify user account matching process.
 /// </summary>
 /// <param name="appUserId">User ID in your app (typically login name)</param>
 /// <param name="appEstablishmentKey">App establishment key (as provided by you to the organization)</param>
 /// <param name="user">User profile</param>
 /// <param name="source">Source of update (sign on or provisioning)</param>
 public virtual void UpdateLinkedUser(string appUserId, string appEstablishmentKey, RmUnifyUser user, Source source)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Log in as a pre-existing user who has been linked to an RM Unify user.
 /// This method is called when single sign on from RM Unify successfully completes.  CreateOrUpdateOrganization()
 /// and CreateOrUpdateUser() will always be called first (in that order) provided the appropriate Ids are available.
 /// Your app should set any session cookies required to log the user in.
 /// Your app should then redirect the user to returnUrl (if set) or to the default URL for this user in your app.
 /// </summary>
 /// <param name="appUserId">User ID in your app (typically login name)</param>
 /// <param name="appEstablishmentKey">App establishment key (as provided by you to the organization)</param>
 /// <param name="user">User profile</param>
 /// <param name="maxSessionEnd">Maxiumum time after which reauthentication should be prompted</param>
 /// <param name="returnUrl">Return URL specified in login request (null if none)</param>
 public virtual void DoLoginForLinkedUser(string appUserId, string appEstablishmentKey, RmUnifyUser user, DateTime maxSessionEnd, string returnUrl)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Log the current user into your app.
 /// This method is called when single sign on from RM Unify successfully completes.  CreateOrUpdateOrganization()
 /// and CreateOrUpdateUser() will always be called first (in that order) provided the appropriate Ids are available.
 /// Your app should set any session cookies required to log the user in.
 /// Your app should then redirect the user to returnUrl (if set) or to the default URL for this user in your app.
 /// </summary>
 /// <param name="user">User profile</param>
 /// <param name="maxSessionEnd">Maxiumum time after which reauthentication should be prompted</param>
 /// <param name="returnUrl">Return URL specified in login request (null if none)</param>
 public abstract void DoLogin(RmUnifyUser user, DateTime maxSessionEnd, string returnUrl);
 /// <summary>
 /// Create a new user or update an existing one.
 /// This method will never be called if the user.Id is null (for example, if neither IdentityGuid nor
 /// PersistentId has been requested from RM Unify).
 /// If your app stores information about a user, it should use user.Id as a key to create a new user record or
 /// update an existing one.
 /// Be aware that it is possible for a user to move organization (i.e. the same user.Id may appear in a different
 /// organization.Id).  In this case, it is safe to delete the old user profile.
 /// </summary>
 /// <param name="user">User profile</param>
 /// <param name="source">Source of update (sign on or provisioning)</param>
 public abstract void CreateOrUpdateUser(RmUnifyUser user, Source source);
        private void CreateOrUpdateUserRoles(RmUnifyUser rmUser)
        {
            string rmRole = null;

            switch (rmUser.UserRole)
            {
                case RmUnifyUser.Role.TeachingStaff:
                case RmUnifyUser.Role.NonTeachingStaff:
                    rmRole = "staff";
                    break;
                case RmUnifyUser.Role.Student:
                    rmRole = "student";
                    break;
            }
            if (rmUser.IsUnifyAdmin)
            {
                rmRole = "admin";
            }
            if (rmRole == null)
            {
                throw new Exception("Sorry, this application does not support users with your role");
            }

            var rolesProvider = (SimpleRoleProvider)Roles.Provider;
            var currentRoles = rolesProvider.GetRolesForUser(rmUser.Id);
            if (!currentRoles.Contains(rmRole))
            {
                var allRoles = rolesProvider.GetAllRoles();
                if (!allRoles.Contains("staff"))
                {
                    rolesProvider.CreateRole("staff");
                }
                if (!allRoles.Contains("student"))
                {
                    rolesProvider.CreateRole("student");
                }
                if (!allRoles.Contains("admin"))
                {
                    rolesProvider.CreateRole("admin");
                }
                rolesProvider.RemoveUsersFromRoles(new string[] { rmUser.Id }, currentRoles.Intersect(new string[] { "staff", "student", "admin" }).ToArray());
                rolesProvider.AddUsersToRoles(new string[] { rmUser.Id }, new string[] { rmRole });
            }
        }
        private void CreateOrUpdateUserData(RmUnifyUser rmUser)
        {
            using (var context = new UsersContext())
            {
                // Get the user (if they exist)
                UserProfile user = (from u in context.UserProfiles
                                    where u.UserName == rmUser.Id
                                    select u).SingleOrDefault();

                if (user == null)
                {
                    // User does not exist - create
                    School school = (from s in context.Schools
                                     where s.RmUnifyOrganizationId == rmUser.Organization.Id
                                     select s).SingleOrDefault();
                    var userdata = new
                    {
                        DisplayName = rmUser.DisplayName,
                        SchoolId = school.Id,
                        LastLogin = DateTime.Now
                    };
                    WebSecurity.CreateUserAndAccount(rmUser.Id, Guid.NewGuid().ToString(), userdata);
                }
                else
                {
                    // User exists - update
                    // We don't need to worry about the user moving school as we are using rmUser.Id
                    // (which will change if the user moves school) rather than rmUser.PersonId (which may not)
                    if (rmUser.DisplayName != user.DisplayName)
                    {
                        user.DisplayName = rmUser.DisplayName;
                    }
                    if (user.Deleted != null)
                    {
                        user.Deleted = null;
                    }
                    user.LastLogin = DateTime.Now;
                    context.SaveChanges();
                }
            }
        }
Esempio n. 11
0
        protected Role GetRole(RmUnifyUser rmUser)
        {
            if (rmUser.IsUnifyAdmin)
            {
                return Role.Admin;
            }

            switch (rmUser.UserRole)
            {
                case RmUnifyUser.Role.TeachingStaff:
                case RmUnifyUser.Role.NonTeachingStaff:
                    return Role.Staff;
                case RmUnifyUser.Role.Parent:
                    return Role.Parent;
                case RmUnifyUser.Role.Student:
                    return Role.Student;
            }

            return Role.Guest;
        }
Esempio n. 12
0
        /// <summary>
        /// Log the current user into your app.
        /// This method is called when single sign on from RM Unify successfully completes.  CreateOrUpdateOrganization()
        /// and CreateOrUpdateUser() will always be called first (in that order) provided the appropriate Ids are available.
        /// Your app should set any session cookies required to log the user in.
        /// Your app should then redirect the user to returnUrl (if set) or to the default URL for this user in your app.
        /// </summary>
        /// <param name="user">User profile</param>
        /// <param name="maxSessionEnd">Maxiumum time after which reauthentication should be prompted</param>
        /// <param name="returnUrl">Return URL specified in login request (null if none)</param>
        public override void DoLogin(RmUnifyUser user, DateTime maxSessionEnd, string returnUrl)
        {
            if (_account == null)
            {
                throw new Exception("DoLogin() called before CreateOrUpdateUser()");
            }

            // Create our own cookie so we can make sure session length is appropriate.
            // Calculate session expiry as minimum of our app policy and that provided by RM Unify
            DateTime endTime = DateTime.Now.Add(FormsAuthentication.Timeout);
            if (endTime > maxSessionEnd)
            {
                endTime = maxSessionEnd;
            }

            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2,
                _account.LoginName,
                DateTime.Now,
                endTime,
                false,
                "",
                FormsAuthentication.FormsCookiePath);
            string encTicket = FormsAuthentication.Encrypt(ticket);
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
            cookie.HttpOnly = true;

            // If your website is entirely https, it is good practise to mark the cookie as secure
            // cookie.Secure = true;
            HttpContext.Current.Response.Cookies.Add(cookie);

            HttpContext.Current.Response.Redirect(returnUrl == null ? "/" : returnUrl, true);
        }
        /// <summary>
        /// Update properties of a pre-existing user that has been linked to RM Unify.
        /// Only necessary if your app supports the RM Unify user account matching process
        /// (http://dev.rmunify.com/reference/supporting-user-account-matching/the-rm-unify-process.aspx).
        /// In this case, the organization has provisioned users into your app outside RM Unify and wishes to connect RM Unify
        /// to their existing users. Their "app establishment key" and the existing user id in your app (typically login name)
        /// is passed in to this method so that you can verify that the user is in the establishment and update them.
        /// Called instead of CreateOrUpdateUser() if the current user has been linked to a user in your app as part of the
        /// RM Unify user account matching process.
        /// </summary>
        /// <param name="appUserId">User ID in your app (typically login name)</param>
        /// <param name="appEstablishmentKey">App establishment key (as provided by you to the organization)</param>
        /// <param name="user">User profile</param>
        /// <param name="source">Source of update (sign on or provisioning)</param>
        public override void UpdateLinkedUser(string appUserId, string appEstablishmentKey, RmUnifyUser rmUser, Source source)
        {
            if (_school == null)
            {
                throw new Exception("UpdateLinkedUser() called before UpdateLinkedOrganization()");
            }

            using (var context = new Context())
            {
                var account = (from a in context.Accounts
                                where a.LoginName == appUserId
                                select a).SingleOrDefault();
                if (account == null)
                {
                    throw new RmUnifySsoException(RmUnifySsoException.ERRORCODES_INVALIDAPPUSERID, "No such username: "******"User " + appUserId + " is not in school with establishment key " + appEstablishmentKey);
                }

                account.DisplayName = rmUser.DisplayName;
                account.RoleEnum = GetRole(rmUser);
                account.DeletedDate = null;  // if previously deleted, restore
                if (source == Source.SingleSignOn)
                {
                    account.LastLogin = DateTime.Now;
                }
                context.SaveChanges();

                // Cache account for next method
                _account = account;
            }
        }