1 using System;
2 using System.Collections.Generic;
3 using System.Net.Http.Headers;
4 using System.Security.Principal;
5 using System.Text;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using System.Web.Http.Filters;
9 using System.Web.Http.Results;
10
11 namespace WebApi
12 {
13 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
14 public class AuthenticateAttribute : FilterAttribute, IAuthenticationFilter
15 {
16 private static readonly Dictionary<string, string> UserAccounts;
17
18 static AuthenticateAttribute()
19 {
20 UserAccounts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
21 {
22 {"Foo", "Password"},
23 {"Bar", "Password"},
24 {"Baz", "Password"}
25 };
26 }
27
28 public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
29 {
30 IPrincipal user = null;
31 var headerValue = context.Request.Headers.Authorization;
32 if (null != headerValue && headerValue.Scheme == "Basic")
33 {
34 var credential = Encoding.Default.GetString(Convert.FromBase64String(headerValue.Parameter));
35 var split = credential.Split(':');
36 if (split.Length == 2)
37 {
38 var userName = split[0];
39 string password;
40 if (UserAccounts.TryGetValue(userName, out password))
41 {
42 if (password == split[1])
43 {
44 var identity = new GenericIdentity(userName);
45 user = new GenericPrincipal(identity, new string[0]);
46 }
47 }
48 }
49 }
50 context.Principal = user;
51 return Task.FromResult<object>(null);
52 }
53
54 public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
55 {
56 var user = context.ActionContext.ControllerContext.RequestContext.Principal;
57 if (null != user && user.Identity.IsAuthenticated) return Task.FromResult<object>(null);
58 var parameter = $"realm={context.Request.RequestUri.DnsSafeHost}";
59 var challenge = new AuthenticationHeaderValue("Basic", parameter);
60 context.Result = new UnauthorizedResult(new[] {challenge}, context.Request);
61 return Task.FromResult<object>(null);
62 }
63 }
64 }