summaryrefslogtreecommitdiffstats
path: root/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs
blob: a322f7dbe214915b802919489c33d8c0a1cafe65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
namespace MvcRelyingParty.Controllers {
	using System;
	using System.Collections.Generic;
	using System.Globalization;
	using System.Linq;
	using System.Net;
	using System.Security.Principal;
	using System.Web;
	using System.Web.Mvc;
	using System.Web.Security;
	using System.Web.UI;
	using DotNetOpenAuth.Messaging;
	using DotNetOpenAuth.OAuth;
	using DotNetOpenAuth.OAuth.Messages;
	using DotNetOpenAuth.OpenId;
	using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
	using DotNetOpenAuth.OpenId.RelyingParty;
	using MvcRelyingParty.Models;
	using RelyingPartyLogic;

	[HandleError]
	public class AccountController : Controller {
		[Authorize]
		public ActionResult Edit() {
			return View(GetAccountInfoModel());
		}

		/// <summary>
		/// Updates the user's account information.
		/// </summary>
		/// <param name="firstName">The first name.</param>
		/// <param name="lastName">The last name.</param>
		/// <param name="emailAddress">The email address.</param>
		/// <returns>An updated view showing the new profile.</returns>
		/// <remarks>
		/// This action accepts PUT because this operation is idempotent in nature.
		/// </remarks>
		[Authorize, AcceptVerbs(HttpVerbs.Put), ValidateAntiForgeryToken]
		public ActionResult Update(string firstName, string lastName, string emailAddress) {
			Database.LoggedInUser.FirstName = firstName;
			Database.LoggedInUser.LastName = lastName;

			if (Database.LoggedInUser.EmailAddress != emailAddress) {
				Database.LoggedInUser.EmailAddress = emailAddress;
				Database.LoggedInUser.EmailAddressVerified = false;
			}

			return PartialView("EditFields", GetAccountInfoModel());
		}

		[Authorize]
		public ActionResult Authorize() {
			if (OAuthServiceProvider.PendingAuthorizationRequest == null) {
				return RedirectToAction("Edit");
			}

			var model = new AccountAuthorizeModel {
				ConsumerApp = OAuthServiceProvider.PendingAuthorizationConsumer.Name,
				IsUnsafeRequest = OAuthServiceProvider.PendingAuthorizationRequest.IsUnsafeRequest,
			};

			return View(model);
		}

		[Authorize, AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
		public ActionResult Authorize(bool isApproved) {
			if (isApproved) {
				var consumer = OAuthServiceProvider.PendingAuthorizationConsumer;
				var tokenManager = OAuthServiceProvider.ServiceProvider.TokenManager;
				var pendingRequest = OAuthServiceProvider.PendingAuthorizationRequest;
				ITokenContainingMessage requestTokenMessage = pendingRequest;
				var requestToken = tokenManager.GetRequestToken(requestTokenMessage.Token);

				var response = OAuthServiceProvider.AuthorizePendingRequestTokenAsWebResponse();
				if (response != null) {
					// The consumer provided a callback URL that can take care of everything else.
					return response.AsActionResult();
				}

				var model = new AccountAuthorizeModel {
					ConsumerApp = consumer.Name,
				};

				if (!pendingRequest.IsUnsafeRequest) {
					model.VerificationCode = ServiceProvider.CreateVerificationCode(consumer.VerificationCodeFormat, consumer.VerificationCodeLength);
					requestToken.VerificationCode = model.VerificationCode;
					tokenManager.UpdateToken(requestToken);
				}

				return View("AuthorizeApproved", model);
			} else {
				OAuthServiceProvider.PendingAuthorizationRequest = null;
				return View("AuthorizeDenied");
			}
		}

		[Authorize, AcceptVerbs(HttpVerbs.Delete)] // ValidateAntiForgeryToken would be GREAT here, but it's not a FORM POST operation so that doesn't work.
		public ActionResult RevokeToken(string token) {
			if (String.IsNullOrEmpty(token)) {
				throw new ArgumentNullException("token");
			}

			var tokenEntity = Database.DataContext.IssuedTokens.OfType<IssuedAccessToken>().Where(t => t.User.UserId == Database.LoggedInUser.UserId && t.Token == token).FirstOrDefault();
			if (tokenEntity == null) {
				throw new ArgumentOutOfRangeException("id", "The logged in user does not have a token with this name to revoke.");
			}

			Database.DataContext.DeleteObject(tokenEntity);
			Database.DataContext.SaveChanges(); // make changes now so the model we fill up reflects the change

			return PartialView("AuthorizedApps", GetAccountInfoModel());
		}

		private static AccountInfoModel GetAccountInfoModel() {
			var authorizedApps = from token in Database.DataContext.IssuedTokens.OfType<IssuedAccessToken>()
								 where token.User.UserId == Database.LoggedInUser.UserId
								 select new AccountInfoModel.AuthorizedApp { AppName = token.Consumer.Name, Token = token.Token };
			Database.LoggedInUser.AuthenticationTokens.Load();
			var model = new AccountInfoModel {
				FirstName = Database.LoggedInUser.FirstName,
				LastName = Database.LoggedInUser.LastName,
				EmailAddress = Database.LoggedInUser.EmailAddress,
				AuthorizedApps = authorizedApps.ToList(),
				AuthenticationTokens = Database.LoggedInUser.AuthenticationTokens.ToList(),
			};
			return model;
		}
	}
}