Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
2feeb48
First working version of Meetup provider
dance2die Feb 23, 2018
c3ee580
Removed commented-out code and an unused using reference
dance2die Feb 24, 2018
a3447be
Mapped all user's claim options
dance2die Feb 24, 2018
7037b3c
Added Meetup provider to the solution
dance2die Feb 24, 2018
42e771c
Updated indentation as suggested by "kinosang" on https://github.com/…
dance2die Feb 24, 2018
522fb33
Fixed indentation as suggested by kinosang on #220
dance2die Feb 24, 2018
8648b81
Introduced a ClaimType static constant class "MeetupClaimTypes" as su…
dance2die Feb 24, 2018
f15cb87
Updated Meetup package author & company in the package (I have forgot…
dance2die Feb 24, 2018
1d66b8f
Migrate to the latest KoreBuild version
kevinchalet Feb 28, 2018
cb903be
First working version of Meetup provider
dance2die Feb 23, 2018
eef1c57
Removed commented-out code and an unused using reference
dance2die Feb 24, 2018
e8a00a2
Mapped all user's claim options
dance2die Feb 24, 2018
4d32726
Added Meetup provider to the solution
dance2die Feb 24, 2018
f3a1c26
Updated indentation as suggested by "kinosang" on https://github.com/…
dance2die Feb 24, 2018
8f6c909
Fixed indentation as suggested by kinosang on #220
dance2die Feb 24, 2018
79d08a8
Introduced a ClaimType static constant class "MeetupClaimTypes" as su…
dance2die Feb 24, 2018
7fe7f1b
Updated Meetup package author & company in the package (I have forgot…
dance2die Feb 24, 2018
ddf0259
Took remote solution
dance2die Feb 28, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
First working version of Meetup provider
  • Loading branch information
dance2die committed Feb 28, 2018
commit cb903bef0d4c4bed8e1d78467401d40ec4d1ce8e
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\..\build\packages.props" />

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<Description>ASP.NET Core security middleware enabling Meetup authentication.</Description>
<Authors>Kévin Chalet;Jerrie Pelser</Authors>
<PackageTags>aspnetcore;authentication;Meetup;oauth;security</PackageTags>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="$(JetBrainsVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OAuth" Version="$(AspNetCoreVersion)" />
</ItemGroup>

</Project>
52 changes: 52 additions & 0 deletions src/AspNet.Security.OAuth.Meetup/MeetupAuthenticationDefaults.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;

namespace AspNet.Security.OAuth.Meetup
{
/// <summary>
/// Default values used by the Meetup authentication middleware.
/// </summary>
public static class MeetupAuthenticationDefaults
{
/// <summary>
/// Default value for <see cref="AuthenticationScheme.Name"/>.
/// </summary>
public const string AuthenticationScheme = "Meetup";

/// <summary>
/// Default value for <see cref="AuthenticationScheme.DisplayName"/>.
/// </summary>
public const string DisplayName = "Meetup";

/// <summary>
/// Default value for <see cref="AuthenticationSchemeOptions.ClaimsIssuer"/>.
/// </summary>
public const string Issuer = "Meetup";

/// <summary>
/// Default value for <see cref="RemoteAuthenticationOptions.CallbackPath"/>.
/// </summary>
public const string CallbackPath = "/signin-meetup";

/// <summary>
/// Default value for <see cref="OAuthOptions.AuthorizationEndpoint"/>.
/// </summary>
public const string AuthorizationEndpoint = "https://secure.meetup.com/oauth2/authorize";

/// <summary>
/// Default value for <see cref="OAuthOptions.TokenEndpoint"/>.
/// </summary>
public const string TokenEndpoint = "https://secure.meetup.com/oauth2/access";

/// <summary>
/// Default value for <see cref="OAuthOptions.UserInformationEndpoint"/>.
/// </summary>
public const string UserInformationEndpoint = "https://api.meetup.com/members/self";
}
}
76 changes: 76 additions & 0 deletions src/AspNet.Security.OAuth.Meetup/MeetupAuthenticationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/

using System;
using AspNet.Security.OAuth.Meetup;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authentication;

namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods to add Meetup authentication capabilities to an HTTP application pipeline.
/// </summary>
public static class MeetupAuthenticationExtensions
{
/// <summary>
/// Adds <see cref="MeetupAuthenticationHandler"/> to the specified
/// <see cref="AuthenticationBuilder"/>, which enables Meetup authentication capabilities.
/// </summary>
/// <param name="builder">The authentication builder.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddMeetup([NotNull] this AuthenticationBuilder builder)
{
return builder.AddMeetup(MeetupAuthenticationDefaults.AuthenticationScheme, options => { });
}

/// <summary>
/// Adds <see cref="MeetupAuthenticationHandler"/> to the specified
/// <see cref="AuthenticationBuilder"/>, which enables Meetup authentication capabilities.
/// </summary>
/// <param name="builder">The authentication builder.</param>
/// <param name="configuration">The delegate used to configure the OpenID 2.0 options.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddMeetup(
[NotNull] this AuthenticationBuilder builder,
[NotNull] Action<MeetupAuthenticationOptions> configuration)
{
return builder.AddMeetup(MeetupAuthenticationDefaults.AuthenticationScheme, configuration);
}

/// <summary>
/// Adds <see cref="MeetupAuthenticationHandler"/> to the specified
/// <see cref="AuthenticationBuilder"/>, which enables Meetup authentication capabilities.
/// </summary>
/// <param name="builder">The authentication builder.</param>
/// <param name="scheme">The authentication scheme associated with this instance.</param>
/// <param name="configuration">The delegate used to configure the Meetup options.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddMeetup(
[NotNull] this AuthenticationBuilder builder, [NotNull] string scheme,
[NotNull] Action<MeetupAuthenticationOptions> configuration)
{
return builder.AddMeetup(scheme, MeetupAuthenticationDefaults.DisplayName, configuration);
}

/// <summary>
/// Adds <see cref="MeetupAuthenticationHandler"/> to the specified
/// <see cref="AuthenticationBuilder"/>, which enables Meetup authentication capabilities.
/// </summary>
/// <param name="builder">The authentication builder.</param>
/// <param name="scheme">The authentication scheme associated with this instance.</param>
/// <param name="caption">The optional display name associated with this instance.</param>
/// <param name="configuration">The delegate used to configure the Meetup options.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddMeetup(
[NotNull] this AuthenticationBuilder builder,
[NotNull] string scheme, [CanBeNull] string caption,
[NotNull] Action<MeetupAuthenticationOptions> configuration)
{
return builder.AddOAuth<MeetupAuthenticationOptions, MeetupAuthenticationHandler>(scheme, caption, configuration);
}
}
}
75 changes: 75 additions & 0 deletions src/AspNet.Security.OAuth.Meetup/MeetupAuthenticationHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/

using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;

namespace AspNet.Security.OAuth.Meetup
{
public class MeetupAuthenticationHandler : OAuthHandler<MeetupAuthenticationOptions>
{
public MeetupAuthenticationHandler(
[NotNull] IOptionsMonitor<MeetupAuthenticationOptions> options,
[NotNull] ILoggerFactory logger,
[NotNull] UrlEncoder encoder,
[NotNull] ISystemClock clock)
: base(options, logger, encoder, clock)
{
}

protected override async Task<AuthenticationTicket> CreateTicketAsync([NotNull] ClaimsIdentity identity,
[NotNull] AuthenticationProperties properties, [NotNull] OAuthTokenResponse tokens)
{
var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);
if (!response.IsSuccessStatusCode)
{
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());

throw new HttpRequestException("An error occurred while retrieving the user profile.");
}

var payload = JObject.Parse(await response.Content.ReadAsStringAsync());

var principal = new ClaimsPrincipal(identity);
var context = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload);
context.RunClaimActions(payload);

//// When the email address is not public, retrieve it from
//// the emails endpoint if the user:email scope is specified.
//if (!string.IsNullOrEmpty(Options.UserEmailsEndpoint) &&
// !identity.HasClaim(claim => claim.Type == ClaimTypes.Email) && Options.Scope.Contains("user:email"))
//{
// var address = await GetEmailAsync(tokens);
// if (!string.IsNullOrEmpty(address))
// {
// identity.AddClaim(new Claim(ClaimTypes.Email, address, ClaimValueTypes.String, Options.ClaimsIssuer));
// }
//}

await Options.Events.CreatingTicket(context);

return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
}
}
36 changes: 36 additions & 0 deletions src/AspNet.Security.OAuth.Meetup/MeetupAuthenticationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/

using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;

namespace AspNet.Security.OAuth.Meetup
{
/// <summary>
/// Defines a set of options used by <see cref="MeetupAuthenticationHandler"/>.
/// </summary>
public class MeetupAuthenticationOptions : OAuthOptions
{
public MeetupAuthenticationOptions()
{
ClaimsIssuer = MeetupAuthenticationDefaults.Issuer;

CallbackPath = new PathString(MeetupAuthenticationDefaults.CallbackPath);

AuthorizationEndpoint = MeetupAuthenticationDefaults.AuthorizationEndpoint;
TokenEndpoint = MeetupAuthenticationDefaults.TokenEndpoint;
UserInformationEndpoint = MeetupAuthenticationDefaults.UserInformationEndpoint;

ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
ClaimActions.MapJsonKey(ClaimTypes.Name, "login");
ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
ClaimActions.MapJsonKey("urn:meetup:name", "name");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #216, it introduces ClaimTypes constants for the claims.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, let me refer to the #216

ClaimActions.MapJsonKey("urn:meetup:url", "url");
}
}
}