diff --git a/.gitignore b/.gitignore index ee0eb3936..00de4cd4d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,10 @@ project.lock.json # Build results +.dotnetcli/ artifacts/ +coverage/ +coverage.* [Dd]ebug/ [Rr]elease/ x64/ diff --git a/AspNet.Security.OAuth.Providers.sln b/AspNet.Security.OAuth.Providers.sln index a3e7e4469..bfcdb2c26 100644 --- a/AspNet.Security.OAuth.Providers.sln +++ b/AspNet.Security.OAuth.Providers.sln @@ -155,11 +155,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.MailR EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.Odnoklassniki", "src\AspNet.Security.OAuth.Odnoklassniki\AspNet.Security.OAuth.Odnoklassniki.csproj", "{27DB335F-5012-4276-98C5-EAEA335C8C7B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNet.Security.OAuth.Trakt", "src\AspNet.Security.OAuth.Trakt\AspNet.Security.OAuth.Trakt.csproj", "{5325536E-8E3A-4611-AB92-B03369493354}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.Trakt", "src\AspNet.Security.OAuth.Trakt\AspNet.Security.OAuth.Trakt.csproj", "{5325536E-8E3A-4611-AB92-B03369493354}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNet.Security.OAuth.Shopify", "src\AspNet.Security.OAuth.Shopify\AspNet.Security.OAuth.Shopify.csproj", "{112F6B50-0FD3-45AA-992E-72D7B873BF00}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.Shopify", "src\AspNet.Security.OAuth.Shopify\AspNet.Security.OAuth.Shopify.csproj", "{112F6B50-0FD3-45AA-992E-72D7B873BF00}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.Client", "samples\Mvc.Client\Mvc.Client.csproj", "{4F389BF3-30B7-43A2-9E14-6450D57D53DB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc.Client", "samples\Mvc.Client\Mvc.Client.csproj", "{140A6CAD-FC84-4A09-A939-8A5692DF0C7C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.GitLab", "src\AspNet.Security.OAuth.GitLab\AspNet.Security.OAuth.GitLab.csproj", "{FACB1C2F-3BF7-4DD3-958B-E471E69E214A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -383,10 +385,14 @@ Global {112F6B50-0FD3-45AA-992E-72D7B873BF00}.Debug|Any CPU.Build.0 = Debug|Any CPU {112F6B50-0FD3-45AA-992E-72D7B873BF00}.Release|Any CPU.ActiveCfg = Release|Any CPU {112F6B50-0FD3-45AA-992E-72D7B873BF00}.Release|Any CPU.Build.0 = Release|Any CPU - {4F389BF3-30B7-43A2-9E14-6450D57D53DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F389BF3-30B7-43A2-9E14-6450D57D53DB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F389BF3-30B7-43A2-9E14-6450D57D53DB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F389BF3-30B7-43A2-9E14-6450D57D53DB}.Release|Any CPU.Build.0 = Release|Any CPU + {140A6CAD-FC84-4A09-A939-8A5692DF0C7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {140A6CAD-FC84-4A09-A939-8A5692DF0C7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {140A6CAD-FC84-4A09-A939-8A5692DF0C7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {140A6CAD-FC84-4A09-A939-8A5692DF0C7C}.Release|Any CPU.Build.0 = Release|Any CPU + {FACB1C2F-3BF7-4DD3-958B-E471E69E214A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FACB1C2F-3BF7-4DD3-958B-E471E69E214A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FACB1C2F-3BF7-4DD3-958B-E471E69E214A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FACB1C2F-3BF7-4DD3-958B-E471E69E214A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -448,7 +454,8 @@ Global {27DB335F-5012-4276-98C5-EAEA335C8C7B} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D} {5325536E-8E3A-4611-AB92-B03369493354} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D} {112F6B50-0FD3-45AA-992E-72D7B873BF00} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D} - {4F389BF3-30B7-43A2-9E14-6450D57D53DB} = {BAC7067D-88FE-4385-8AC9-1A325FFBDE69} + {140A6CAD-FC84-4A09-A939-8A5692DF0C7C} = {BAC7067D-88FE-4385-8AC9-1A325FFBDE69} + {FACB1C2F-3BF7-4DD3-958B-E471E69E214A} = {C1352FD3-AE8B-43EE-B45B-F6E0B3FBAC6D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C7B54DE2-6407-4802-AD9C-CE54BF414C8C} diff --git a/README.md b/README.md index 35659b6f2..02db921f9 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ We would love it if you could help contributing to this repository. * [Tathagata Chakraborty](https://github.com/tatx) * [TheUltimateC0der](https://github.com/TheUltimateC0der) * [Tommy Parnell](https://github.com/tparnell8) +* [twsl](https://github.com/twsI) * [Yannic Smeets](https://github.com/yannicsmeets) * [zAfLu](https://github.com/zAfLu) * [zhengchun](https://github.com/zhengchun) @@ -121,6 +122,7 @@ If a provider you're looking for does not exist, consider making a PR to add one | Fitbit | [![NuGet](https://buildstats.info/nuget/AspNet.Security.OAuth.Fitbit?includePreReleases=false)](https://www.nuget.org/packages/AspNet.Security.OAuth.Fitbit/ "Download AspNet.Security.OAuth.Fitbit from NuGet.org") | [![MyGet](https://buildstats.info/myget/aspnet-contrib/AspNet.Security.OAuth.Fitbit?includePreReleases=false)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Fitbit "Download AspNet.Security.OAuth.Fitbit from MyGet.org") | [Documentation](https://dev.fitbit.com/build/reference/web-api/oauth2/ "Fitbit developer documentation") | | Foursquare | [![NuGet](https://buildstats.info/nuget/AspNet.Security.OAuth.Foursquare?includePreReleases=false)](https://www.nuget.org/packages/AspNet.Security.OAuth.Foursquare/ "Download AspNet.Security.OAuth.Foursquare from NuGet.org") | [![MyGet](https://buildstats.info/myget/aspnet-contrib/AspNet.Security.OAuth.Foursquare?includePreReleases=false)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Foursquare "Download AspNet.Security.OAuth.Foursquare from MyGet.org") | [Documentation](https://developer.foursquare.com/docs/api/configuration/authentication "Foursquare developer documentation") | | GitHub | [![NuGet](https://buildstats.info/nuget/AspNet.Security.OAuth.GitHub?includePreReleases=false)](https://www.nuget.org/packages/AspNet.Security.OAuth.GitHub/ "Download AspNet.Security.OAuth.GitHub from NuGet.org") | [![MyGet](https://buildstats.info/myget/aspnet-contrib/AspNet.Security.OAuth.GitHub?includePreReleases=false)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.GitHub "Download AspNet.Security.OAuth.GitHub from MyGet.org") | [Documentation](https://developer.github.com/apps/building-oauth-apps/ "GitHub developer documentation") | +| GitLab | [![NuGet](https://buildstats.info/nuget/AspNet.Security.OAuth.GitLab?includePreReleases=false)](https://www.nuget.org/packages/AspNet.Security.OAuth.GitLab/ "Download AspNet.Security.OAuth.GitLab from NuGet.org") | [![MyGet](https://buildstats.info/myget/aspnet-contrib/AspNet.Security.OAuth.GitLab?includePreReleases=false)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.GitLab "Download AspNet.Security.OAuth.GitLab from MyGet.org") | [Documentation](https://docs.gitlab.com/ee/api/oauth2.html "GitLab developer documentation") | | Gitter | [![NuGet](https://buildstats.info/nuget/AspNet.Security.OAuth.Gitter?includePreReleases=false)](https://www.nuget.org/packages/AspNet.Security.OAuth.Gitter/ "Download AspNet.Security.OAuth.Gitter from NuGet.org") | [![MyGet](https://buildstats.info/myget/aspnet-contrib/AspNet.Security.OAuth.Gitter?includePreReleases=false)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Gitter "Download AspNet.Security.OAuth.Gitter from MyGet.org") | [Documentation](https://developer.gitter.im/docs/authentication "Gitter developer documentation") | | Harvest | [![NuGet](https://buildstats.info/nuget/AspNet.Security.OAuth.Harvest?includePreReleases=false)](https://www.nuget.org/packages/AspNet.Security.OAuth.Harvest/ "Download AspNet.Security.OAuth.Harvest from NuGet.org") | [![MyGet](https://buildstats.info/myget/aspnet-contrib/AspNet.Security.OAuth.Harvest?includePreReleases=false)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Harvest "Download AspNet.Security.OAuth.Harvest from MyGet.org") | [Documentation](https://help.getharvest.com/api-v1/authentication/authentication/oauth/ "Harvest developer documentation") | | HealthGraph (Runkeeper) | [![NuGet](https://buildstats.info/nuget/AspNet.Security.OAuth.HealthGraph?includePreReleases=false)](https://www.nuget.org/packages/AspNet.Security.OAuth.HealthGraph/ "Download AspNet.Security.OAuth.HealthGraph from NuGet.org") | [![MyGet](https://buildstats.info/myget/aspnet-contrib/AspNet.Security.OAuth.HealthGraph?includePreReleases=false)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.HealthGraph "Download AspNet.Security.OAuth.HealthGraph from MyGet.org") | N/A | diff --git a/samples/Mvc.Client/Startup.cs b/samples/Mvc.Client/Startup.cs index 5a51321cf..99379a07d 100644 --- a/samples/Mvc.Client/Startup.cs +++ b/samples/Mvc.Client/Startup.cs @@ -1,4 +1,4 @@ -/* +/* * 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. diff --git a/src/AspNet.Security.OAuth.GitLab/AspNet.Security.OAuth.GitLab.csproj b/src/AspNet.Security.OAuth.GitLab/AspNet.Security.OAuth.GitLab.csproj new file mode 100644 index 000000000..2983dd79d --- /dev/null +++ b/src/AspNet.Security.OAuth.GitLab/AspNet.Security.OAuth.GitLab.csproj @@ -0,0 +1,20 @@ + + + + + + netcoreapp3.0 + + + + ASP.NET Core security middleware enabling GitLab authentication. + twsl + aspnetcore;authentication;gitlab;oauth;security + + + + + + + + diff --git a/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationConstants.cs b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationConstants.cs new file mode 100644 index 000000000..c1e66619f --- /dev/null +++ b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationConstants.cs @@ -0,0 +1,21 @@ +/* + * 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. + */ + +namespace AspNet.Security.OAuth.GitLab +{ + /// + /// Contains constants specific to the . + /// + public static class GitLabAuthenticationConstants + { + public static class Claims + { + public const string Name = "urn:gitlab:name"; + public const string Avatar = "urn:gitlab:avatar"; + public const string Url = "urn:gitlab:url"; + } + } +} diff --git a/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationDefaults.cs b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationDefaults.cs new file mode 100644 index 000000000..7f7aec237 --- /dev/null +++ b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationDefaults.cs @@ -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.GitLab +{ + /// + /// Default values used by the GitLab authentication middleware. + /// + public class GitLabAuthenticationDefaults + { + /// + /// Default value for . + /// + public const string AuthenticationScheme = "GitLab"; + + /// + /// Default value for . + /// + public static readonly string DisplayName = "GitLab"; + + /// + /// Default value for . + /// + public const string Issuer = "GitLab"; + + /// + /// Default value for . + /// + public const string CallbackPath = "/signin-gitlab"; + + /// + /// Default value for . + /// + public static readonly string AuthorizationEndpoint = "https://gitlab.com/oauth/authorize"; + + /// + /// Default value for . + /// + public static readonly string TokenEndpoint = "https://gitlab.com/oauth/token"; + + /// + /// Default value for . + /// + public static readonly string UserInformationEndpoint = "https://gitlab.com/api/v4/user"; + } +} diff --git a/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationExtensions.cs b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationExtensions.cs new file mode 100644 index 000000000..bb761f310 --- /dev/null +++ b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationExtensions.cs @@ -0,0 +1,78 @@ +/* + * 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.GitLab; +using JetBrains.Annotations; +using Microsoft.AspNetCore.Authentication; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// Extension methods to add GitLab authentication capabilities to an HTTP application pipeline. + /// + public static class GitLabAuthenticationExtensions + { + /// + /// Adds to the specified + /// , which enables GitLab authentication capabilities. + /// + /// The authentication builder. + /// A reference to this instance after the operation has completed. + public static AuthenticationBuilder AddGitLab([NotNull] this AuthenticationBuilder builder) + { + return builder.AddGitLab(GitLabAuthenticationDefaults.AuthenticationScheme, _ => { }); + } + + /// + /// Adds to the specified + /// , which enables GitLab authentication capabilities. + /// + /// The authentication builder. + /// The delegate used to configure the OpenID 2.0 options. + /// A reference to this instance after the operation has completed. + public static AuthenticationBuilder AddGitLab( + [NotNull] this AuthenticationBuilder builder, + [NotNull] Action configuration) + { + return builder.AddGitLab(GitLabAuthenticationDefaults.AuthenticationScheme, configuration); + } + + /// + /// Adds to the specified + /// , which enables GitLab authentication capabilities. + /// + /// The authentication builder. + /// The authentication scheme associated with this instance. + /// The delegate used to configure the GitLab options. + /// The . + public static AuthenticationBuilder AddGitLab( + [NotNull] this AuthenticationBuilder builder, + [NotNull] string scheme, + [NotNull] Action configuration) + { + return builder.AddGitLab(scheme, GitLabAuthenticationDefaults.DisplayName, configuration); + } + + /// + /// Adds to the specified + /// , which enables GitLab authentication capabilities. + /// + /// The authentication builder. + /// The authentication scheme associated with this instance. + /// The optional display name associated with this instance. + /// The delegate used to configure the GitLab options. + /// The . + public static AuthenticationBuilder AddGitLab( + [NotNull] this AuthenticationBuilder builder, + [NotNull] string scheme, + [NotNull] string caption, + [NotNull] Action configuration) + { + return builder.AddOAuth(scheme, caption, configuration); + } + } +} diff --git a/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationHandler.cs b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationHandler.cs new file mode 100644 index 000000000..37648ef35 --- /dev/null +++ b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationHandler.cs @@ -0,0 +1,64 @@ +/* + * 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.Text.Encodings.Web; +using System.Text.Json; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.OAuth; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace AspNet.Security.OAuth.GitLab +{ + public class GitLabAuthenticationHandler : OAuthHandler + { + public GitLabAuthenticationHandler( + [NotNull] IOptionsMonitor options, + [NotNull] ILoggerFactory logger, + [NotNull] UrlEncoder encoder, + [NotNull] ISystemClock clock) + : base(options, logger, encoder, clock) + { + } + + protected override async Task CreateTicketAsync( + ClaimsIdentity identity, + AuthenticationProperties properties, + OAuthTokenResponse tokens) + { + // Get the GitLab user + 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."); + } + + using var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); + + var principal = new ClaimsPrincipal(identity); + var context = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement); + context.RunClaimActions(); + + await Options.Events.CreatingTicket(context); + return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name); + } + } +} diff --git a/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationOptions.cs b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationOptions.cs new file mode 100644 index 000000000..2c8b5b430 --- /dev/null +++ b/src/AspNet.Security.OAuth.GitLab/GitLabAuthenticationOptions.cs @@ -0,0 +1,42 @@ +/* + * 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 static AspNet.Security.OAuth.GitLab.GitLabAuthenticationConstants; + +namespace AspNet.Security.OAuth.GitLab +{ + /// + /// Defines a set of options used by . + /// + public class GitLabAuthenticationOptions : OAuthOptions + { + /// + /// Initializes a new instance of the class. + /// + public GitLabAuthenticationOptions() + { + AuthorizationEndpoint = GitLabAuthenticationDefaults.AuthorizationEndpoint; + CallbackPath = GitLabAuthenticationDefaults.CallbackPath; + TokenEndpoint = GitLabAuthenticationDefaults.TokenEndpoint; + UserInformationEndpoint = GitLabAuthenticationDefaults.UserInformationEndpoint; + + Scope.Add("openid"); + Scope.Add("profile"); + Scope.Add("email"); + Scope.Add("read_user"); + + ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id"); + ClaimActions.MapJsonKey(ClaimTypes.Name, "username"); + ClaimActions.MapJsonKey(ClaimTypes.Email, "email"); + ClaimActions.MapJsonKey(Claims.Name, "name"); + ClaimActions.MapJsonKey(Claims.Avatar, "avatar_url"); + ClaimActions.MapJsonKey(Claims.Url, "web_url"); + } + } +} diff --git a/test/AspNet.Security.OAuth.Providers.Tests/GitLab/GitLabTests.cs b/test/AspNet.Security.OAuth.Providers.Tests/GitLab/GitLabTests.cs new file mode 100644 index 000000000..2e8cab8f2 --- /dev/null +++ b/test/AspNet.Security.OAuth.Providers.Tests/GitLab/GitLabTests.cs @@ -0,0 +1,54 @@ +/* + * 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 System.Threading.Tasks; +using AspNet.Security.OAuth.GitLab; +using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.DependencyInjection; +using Xunit; +using Xunit.Abstractions; + +namespace AspNet.Security.OAuth.GitLab +{ + public class GitLabTests : OAuthTests + { + public GitLabTests(ITestOutputHelper outputHelper) + { + OutputHelper = outputHelper; + } + + public override string DefaultScheme => GitLabAuthenticationDefaults.AuthenticationScheme; + + protected internal override void RegisterAuthentication(AuthenticationBuilder builder) + { + builder.AddGitLab(options => + { + ConfigureDefaults(builder, options); + }); + } + + [Theory] + [InlineData(ClaimTypes.NameIdentifier, "1")] + [InlineData(ClaimTypes.Name, "testuser")] + [InlineData(ClaimTypes.Email, "testuser@gitlab.com")] + [InlineData(GitLabAuthenticationConstants.Claims.Name, "test user")] + [InlineData(GitLabAuthenticationConstants.Claims.Url, "https://gitlab.com/testuser")] + [InlineData(GitLabAuthenticationConstants.Claims.Avatar, "https://assets.gitlab-static.net/uploads/-/system/user/avatar/1234567/avatar.png")] + public async Task Can_Sign_In_Using_GitHub(string claimType, string claimValue) + { + // Arrange + using (var server = CreateTestServer()) + { + // Act + var claims = await AuthenticateUserAsync(server); + + // Assert + AssertClaim(claims, claimType, claimValue); + } + } + } +} diff --git a/test/AspNet.Security.OAuth.Providers.Tests/GitLab/bundle.json b/test/AspNet.Security.OAuth.Providers.Tests/GitLab/bundle.json new file mode 100644 index 000000000..3613f2446 --- /dev/null +++ b/test/AspNet.Security.OAuth.Providers.Tests/GitLab/bundle.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://raw.githubusercontent.com/justeat/httpclient-interception/master/src/HttpClientInterception/Bundles/http-request-bundle-schema.json", + "items": [ + { + "comment": "See https://docs.gitlab.com/ee/api/oauth2.html", + "uri": "https://gitlab.com/oauth/token", + "method": "POST", + "contentFormat": "json", + "contentJson": { + "access_token": "secret-access-token", + "created_at": 1557704714, + "refresh_token": "secret-access-token", + "token_type": "bearer", + "scope": "openid profile email read_user" + } + }, + { + "comment": "See https://docs.gitlab.com/ee/api/oauth2.html", + "uri": "https://gitlab.com/api/v4/user", + "contentFormat": "json", + "contentJson": { + "id": 1, + "name": "test user", + "username": "testuser", + "state": "active", + "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/1234567/avatar.png", + "web_url": "https://gitlab.com/testuser", + "created_at": "2019-07-01T13:00:00.000Z", + "bio": "", + "location": "", + "public_email": "", + "skype": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "organization": "", + "last_sign_in_at": "2019-07-05T13:00:00.000Z", + "confirmed_at": "2019-07-01T15:00:00.000Z", + "last_activity_on": "2019-07-22", + "email": "testuser@gitlab.com", + "theme_id": null, + "color_scheme_id": 1, + "projects_limit": 100000, + "current_sign_in_at": "2019-07-15T13:00:00.000Z", + "identities": [], + "can_create_group": true, + "can_create_project": true, + "two_factor_enabled": false, + "external": false, + "private_profile": true, + "shared_runners_minutes_limit": 2000, + "extra_shared_runners_minutes_limit": null + } + } + ] +}