| 
7 | 7 | using System.Net.Http;  | 
8 | 8 | using System.Net.Http.Headers;  | 
9 | 9 | using System.Security.Claims;  | 
 | 10 | +using System.Text.Encodings.Web;  | 
10 | 11 | using System.Threading.Tasks;  | 
11 |  | -using AspNet.Security.OAuth.Extensions;  | 
12 | 12 | using JetBrains.Annotations;  | 
13 | 13 | using Microsoft.AspNetCore.Authentication;  | 
14 | 14 | using Microsoft.AspNetCore.Authentication.OAuth;  | 
15 |  | -using Microsoft.AspNetCore.Http.Authentication;  | 
 | 15 | +using Microsoft.AspNetCore.WebUtilities;  | 
16 | 16 | using Microsoft.Extensions.Logging;  | 
 | 17 | +using Microsoft.Extensions.Options;  | 
17 | 18 | using Newtonsoft.Json.Linq;  | 
18 | 19 | 
 
  | 
19 |  | -namespace AspNet.Security.OAuth.<%= name %> {  | 
20 |  | -    public class <%= name %>AuthenticationHandler : OAuthHandler<<%= name %>AuthenticationOptions> {  | 
21 |  | -        public <%= name %>AuthenticationHandler([NotNull] HttpClient client)  | 
22 |  | -            : base(client) {  | 
 | 20 | +namespace AspNet.Security.OAuth.<%= name %>  | 
 | 21 | +{  | 
 | 22 | +    /// <summary>  | 
 | 23 | +    /// Defines a handler for authentication using <%= name %>.  | 
 | 24 | +    /// </summary>  | 
 | 25 | +    public class <%= name %>AuthenticationHandler : OAuthHandler<<%= name %>AuthenticationOptions>  | 
 | 26 | +    {  | 
 | 27 | +        /// <summary>  | 
 | 28 | +        /// Initializes a new instance of the <see cref="<%= name %>AuthenticationHandler"/> class.  | 
 | 29 | +        /// </summary>  | 
 | 30 | +        /// <param name="options">The authentication options.</param>  | 
 | 31 | +        /// <param name="logger">The logger to use.</param>  | 
 | 32 | +        /// <param name="encoder">The URL encoder to use.</param>  | 
 | 33 | +        /// <param name="clock">The system clock to use.</param>  | 
 | 34 | +        public <%= name %>AuthenticationHandler(  | 
 | 35 | +            [NotNull] IOptionsMonitor<<%= name %>AuthenticationOptions> options,  | 
 | 36 | +            [NotNull] ILoggerFactory logger,  | 
 | 37 | +            [NotNull] UrlEncoder encoder,  | 
 | 38 | +            [NotNull] ISystemClock clock)  | 
 | 39 | +            : base(options, logger, encoder, clock)  | 
 | 40 | +        {  | 
23 | 41 |         }  | 
24 | 42 | 
 
  | 
25 |  | -        protected override async Task<AuthenticationTicket> CreateTicketAsync([NotNull] ClaimsIdentity identity,  | 
26 |  | -            [NotNull] AuthenticationProperties properties, [NotNull] OAuthTokenResponse tokens) {  | 
27 |  | -            var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);  | 
 | 43 | +        /// <inheritdoc />  | 
 | 44 | +        protected override async Task<AuthenticationTicket> CreateTicketAsync(  | 
 | 45 | +            [NotNull] ClaimsIdentity identity,  | 
 | 46 | +            [NotNull] AuthenticationProperties properties,  | 
 | 47 | +            [NotNull] OAuthTokenResponse tokens)  | 
 | 48 | +        {  | 
 | 49 | +            var endpoint = Options.UserInformationEndpoint;  | 
 | 50 | + | 
 | 51 | +            // TODO Append any additional query string parameters required  | 
 | 52 | +            //endpoint = QueryHelpers.AddQueryString(endpoint, "token", tokens.AccessToken);  | 
 | 53 | + | 
 | 54 | +            var request = new HttpRequestMessage(HttpMethod.Get, endpoint);  | 
28 | 55 |             request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  | 
29 |  | -            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);  | 
30 | 56 | 
 
  | 
31 |  | -            var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);  | 
32 |  | -            response.EnsureSuccessStatusCode();  | 
 | 57 | +            // TODO Add any HTTP request headers required  | 
 | 58 | +            //request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);  | 
33 | 59 | 
 
  | 
34 |  | -            var payload = JObject.Parse(await response.Content.ReadAsStringAsync());  | 
 | 60 | +            var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);  | 
 | 61 | +            if (!response.IsSuccessStatusCode)  | 
 | 62 | +            {  | 
 | 63 | +                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +  | 
 | 64 | +                                "returned a {Status} response with the following payload: {Headers} {Body}.",  | 
 | 65 | +                                /* Status: */ response.StatusCode,  | 
 | 66 | +                                /* Headers: */ response.Headers.ToString(),  | 
 | 67 | +                                /* Body: */ await response.Content.ReadAsStringAsync());  | 
35 | 68 | 
 
  | 
36 |  | -            identity.AddOptionalClaim(ClaimTypes.NameIdentifier, <%= name %>AuthenticationHelper.GetIdentifier(payload), Options.ClaimsIssuer);  | 
 | 69 | +                throw new HttpRequestException("An error occurred while retrieving the user profile from <%= name %>.");  | 
 | 70 | +            }  | 
37 | 71 | 
 
  | 
38 |  | -            // TODO: Add any optional claims, eg  | 
39 |  | -            //  .AddOptionalClaim("urn:<%= name.toLowerCase() %>:name", <%= name %>AuthenticationHelper.GetName(payload), Options.ClaimsIssuer)  | 
 | 72 | +            var payload = JObject.Parse(await response.Content.ReadAsStringAsync());  | 
40 | 73 | 
 
  | 
41 | 74 |             var principal = new ClaimsPrincipal(identity);  | 
42 |  | -            var ticket = new AuthenticationTicket(principal, properties, Options.AuthenticationScheme);  | 
 | 75 | +            var context = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload);  | 
 | 76 | +            context.RunClaimActions(payload);  | 
43 | 77 | 
 
  | 
44 |  | -            var context = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, payload);  | 
45 | 78 |             await Options.Events.CreatingTicket(context);  | 
46 |  | - | 
47 |  | -            return context.Ticket;  | 
 | 79 | +            return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);  | 
48 | 80 |         }  | 
49 | 81 |     }  | 
50 | 82 | }  | 
0 commit comments