Skip to content

Commit

Permalink
Add a Gitter.im provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Lorac authored and kevinchalet committed Jun 2, 2016
1 parent 14618f6 commit 7c76ee4
Show file tree
Hide file tree
Showing 10 changed files with 349 additions and 0 deletions.
7 changes: 7 additions & 0 deletions AspNet.Security.OAuth.Providers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AspNet.Security.OAuth.ArcGI
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AspNet.Security.OAuth.Salesforce", "src\AspNet.Security.OAuth.Salesforce\AspNet.Security.OAuth.Salesforce.xproj", "{5881BB63-89BD-4397-A61C-69B1844F7615}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AspNet.Security.OAuth.Gitter", "src\AspNet.Security.OAuth.Gitter\AspNet.Security.OAuth.Gitter.xproj", "{EDD1BA76-D656-4513-BC65-FEC688CBB9F8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -175,6 +177,10 @@ Global
{5881BB63-89BD-4397-A61C-69B1844F7615}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5881BB63-89BD-4397-A61C-69B1844F7615}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5881BB63-89BD-4397-A61C-69B1844F7615}.Release|Any CPU.Build.0 = Release|Any CPU
{EDD1BA76-D656-4513-BC65-FEC688CBB9F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDD1BA76-D656-4513-BC65-FEC688CBB9F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDD1BA76-D656-4513-BC65-FEC688CBB9F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDD1BA76-D656-4513-BC65-FEC688CBB9F8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -207,5 +213,6 @@ Global
{AC651C2B-C879-41E2-96E0-78D3F0888246} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D}
{1302E67D-5448-407B-8B8D-709A0BA458E8} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D}
{5881BB63-89BD-4397-A61C-69B1844F7615} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D}
{EDD1BA76-D656-4513-BC65-FEC688CBB9F8} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D}
EndGlobalSection
EndGlobal
1 change: 1 addition & 0 deletions samples/Mvc.Client/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"AspNet.Security.OAuth.Foursquare": { "target": "project" },
"AspNet.Security.OAuth.Fitbit": { "target": "project" },
"AspNet.Security.OAuth.GitHub": { "target": "project" },
"AspNet.Security.OAuth.Gitter": { "target": "project" },
"AspNet.Security.OAuth.HealthGraph": { "target": "project" },
"AspNet.Security.OAuth.Imgur": { "target": "project" },
"AspNet.Security.OAuth.Instagram": { "target": "project" },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>edd1ba76-d656-4513-bc65-fec688cbb9f8</ProjectGuid>
<RootNamespace>AspNet.Security.OAuth.Gitter</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
49 changes: 49 additions & 0 deletions src/AspNet.Security.OAuth.Gitter/GitterAuthenticationDefaults.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.Builder;

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

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

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

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

/// <summary>
/// Default value for <see cref="OAuthOptions.AuthorizationEndpoint"/>.
/// </summary>
public const string AuthorizationEndpoint = "https://gitter.im/login/oauth/authorize";

/// <summary>
/// Default value for <see cref="OAuthOptions.TokenEndpoint"/>.
/// </summary>
public const string TokenEndpoint = "https://gitter.im/login/oauth/token";

/// <summary>
/// Default value for <see cref="OAuthOptions.UserInformationEndpoint"/>.
/// </summary>
public const string UserInformationEndpoint = "https://api.gitter.im/v1/user";
}
}
62 changes: 62 additions & 0 deletions src/AspNet.Security.OAuth.Gitter/GitterAuthenticationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.Gitter;
using JetBrains.Annotations;
using Microsoft.Extensions.Options;

namespace Microsoft.AspNetCore.Builder {
/// <summary>
/// Extension methods to add Gitter authentication capabilities to an HTTP application pipeline.
/// </summary>
public static class GitterAuthenticationExtensions {
/// <summary>
/// Adds the <see cref="GitterAuthenticationMiddleware"/> middleware to the specified
/// <see cref="IApplicationBuilder"/>, which enables GitHub authentication capabilities.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>
/// <param name="options">A <see cref="GitterAuthenticationOptions"/> that specifies options for the middleware.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
public static IApplicationBuilder UseGitterAuthentication(
[NotNull] this IApplicationBuilder app,
[NotNull] GitterAuthenticationOptions options) {
if (app == null) {
throw new ArgumentNullException(nameof(app));
}

if (options == null) {
throw new ArgumentNullException(nameof(options));
}

return app.UseMiddleware<GitterAuthenticationMiddleware>(Options.Create(options));
}

/// <summary>
/// Adds the <see cref="GitterAuthenticationMiddleware"/> middleware to the specified
/// <see cref="IApplicationBuilder"/>, which enables Gitter authentication capabilities.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>
/// <param name="configuration">An action delegate to configure the provided <see cref="GitterAuthenticationOptions"/>.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
public static IApplicationBuilder UseGitterAuthentication(
[NotNull] this IApplicationBuilder app,
[NotNull] Action<GitterAuthenticationOptions> configuration) {
if (app == null) {
throw new ArgumentNullException(nameof(app));
}

if (configuration == null) {
throw new ArgumentNullException(nameof(configuration));
}

var options = new GitterAuthenticationOptions();
configuration(options);

return app.UseMiddleware<GitterAuthenticationMiddleware>(Options.Create(options));
}
}
}
60 changes: 60 additions & 0 deletions src/AspNet.Security.OAuth.Gitter/GitterAuthenticationHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using AspNet.Security.OAuth.Extensions;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;

namespace AspNet.Security.OAuth.Gitter {
public class GitterAuthenticationHandler : OAuthHandler<GitterAuthenticationOptions> {
public GitterAuthenticationHandler([NotNull] HttpClient client)
: base(client) {
}

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(tokens.TokenType, tokens.AccessToken);

var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);
if (!response.IsSuccessStatusCode) {
Logger.LogError("An error occurred when 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 when retrieving the user profile.");
}

var payload = JArray.Parse(await response.Content.ReadAsStringAsync());
var user = (JObject) payload[0];

identity.AddOptionalClaim(ClaimTypes.NameIdentifier, GitterAuthenticationHelper.GetIdentifier(user), Options.ClaimsIssuer)
.AddOptionalClaim(ClaimTypes.Name, GitterAuthenticationHelper.GetUsername(user), Options.ClaimsIssuer)
.AddOptionalClaim(ClaimTypes.Webpage, GitterAuthenticationHelper.GetLink(user), Options.ClaimsIssuer)
.AddOptionalClaim("urn:gitter:displayname", GitterAuthenticationHelper.GetDisplayName(user), Options.ClaimsIssuer)
.AddOptionalClaim("urn:gitter:avatarurlsmall", GitterAuthenticationHelper.GetAvatarUrlSmall(user), Options.ClaimsIssuer)
.AddOptionalClaim("urn:gitter:avatarurlmedium", GitterAuthenticationHelper.GetAvatarUrlMedium(user), Options.ClaimsIssuer);

var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, properties, Options.AuthenticationScheme);

var context = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, user);
await Options.Events.CreatingTicket(context);

return context.Ticket;
}
}
}
46 changes: 46 additions & 0 deletions src/AspNet.Security.OAuth.Gitter/GitterAuthenticationHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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 JetBrains.Annotations;
using Newtonsoft.Json.Linq;

namespace AspNet.Security.OAuth.Gitter {
/// <summary>
/// Contains static methods that allow to extract user's information from a <see cref="JObject"/>
/// instance retrieved from GitHub after a successful authentication process.
/// </summary>
public static class GitterAuthenticationHelper {
/// <summary>
/// Gets the username corresponding to the authenticated user.
/// </summary>
public static string GetUsername([NotNull] JObject user) => user.Value<string>("username");

/// <summary>
/// Gets the identifier corresponding to the authenticated user.
/// </summary>
public static string GetIdentifier([NotNull] JObject user) => user.Value<string>("id");

/// <summary>
/// Gets the display name corresponding to the authenticated user.
/// </summary>
public static string GetDisplayName([NotNull] JObject user) => user.Value<string>("displayName");

/// <summary>
/// Gets the URL corresponding to the authenticated user.
/// </summary>
public static string GetLink([NotNull] JObject user) => user.Value<string>("url");

/// <summary>
/// Gets the small url avatar corresponding to the authenticated user.
/// </summary>
public static string GetAvatarUrlSmall([NotNull] JObject user) => user.Value<string>("avatarUrlSmall");

/// <summary>
/// Gets the medium url avatar corresponding to the authenticated user.
/// </summary>
public static string GetAvatarUrlMedium([NotNull] JObject user) => user.Value<string>("avatarUrlMedium");
}
}
32 changes: 32 additions & 0 deletions src/AspNet.Security.OAuth.Gitter/GitterAuthenticationMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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.Text.Encodings.Web;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace AspNet.Security.OAuth.Gitter {
public class GitterAuthenticationMiddleware : OAuthMiddleware<GitterAuthenticationOptions> {
public GitterAuthenticationMiddleware(
[NotNull] RequestDelegate next,
[NotNull] IDataProtectionProvider dataProtectionProvider,
[NotNull] ILoggerFactory loggerFactory,
[NotNull] UrlEncoder encoder,
[NotNull] IOptions<SharedAuthenticationOptions> sharedOptions,
[NotNull] IOptions<GitterAuthenticationOptions> options)
: base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options) {
}

protected override AuthenticationHandler<GitterAuthenticationOptions> CreateHandler() {
return new GitterAuthenticationHandler(Backchannel);
}
}
}
24 changes: 24 additions & 0 deletions src/AspNet.Security.OAuth.Gitter/GitterAuthenticationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.Builder;
using Microsoft.AspNetCore.Http;

namespace AspNet.Security.OAuth.Gitter {
public class GitterAuthenticationOptions : OAuthOptions {
public GitterAuthenticationOptions() {
AuthenticationScheme = GitterAuthenticationDefaults.AuthenticationScheme;
DisplayName = GitterAuthenticationDefaults.DisplayName;
ClaimsIssuer = GitterAuthenticationDefaults.Issuer;

CallbackPath = new PathString(GitterAuthenticationDefaults.CallbackPath);

AuthorizationEndpoint = GitterAuthenticationDefaults.AuthorizationEndpoint;
TokenEndpoint = GitterAuthenticationDefaults.TokenEndpoint;
UserInformationEndpoint = GitterAuthenticationDefaults.UserInformationEndpoint;
}
}
}
50 changes: 50 additions & 0 deletions src/AspNet.Security.OAuth.Gitter/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"version": "1.0.0-beta1-*",

"description": "ASP.NET Core security middleware enabling Gitter authentication.",
"authors": [ "Maxime Roussin-Bélanger" ],

"packOptions": {
"owners": [ "Kévin Chalet", "Jerrie Pelser" ],

"projectUrl": "https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers",
"iconUrl": "https://avatars3.githubusercontent.com/u/7998081?s=64",
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.html",

"repository": {
"type": "git",
"url": "git://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers"
},

"tags": [
"aspnetcore",
"authentication",
"gitter",
"oauth",
"security"
]
},

"buildOptions": {
"warningsAsErrors": true,
"nowarn": [ "CS1591" ],
"xmlDoc": true
},

"dependencies": {
"AspNet.Security.OAuth.Extensions": { "target": "project", "type": "build" },
"JetBrains.Annotations": { "type": "build", "version": "10.1.4" },
"Microsoft.AspNetCore.Authentication.OAuth": "1.0.0-*"
},

"frameworks": {
"net451": { },

"netstandard1.3": {
"imports": [
"dotnet5.4",
"portable-net451+win8"
]
}
}
}

0 comments on commit 7c76ee4

Please sign in to comment.