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 | [](https://www.nuget.org/packages/AspNet.Security.OAuth.Fitbit/ "Download AspNet.Security.OAuth.Fitbit from NuGet.org") | [](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 | [](https://www.nuget.org/packages/AspNet.Security.OAuth.Foursquare/ "Download AspNet.Security.OAuth.Foursquare from NuGet.org") | [](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 | [](https://www.nuget.org/packages/AspNet.Security.OAuth.GitHub/ "Download AspNet.Security.OAuth.GitHub from NuGet.org") | [](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 | [](https://www.nuget.org/packages/AspNet.Security.OAuth.GitLab/ "Download AspNet.Security.OAuth.GitLab from NuGet.org") | [](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 | [](https://www.nuget.org/packages/AspNet.Security.OAuth.Gitter/ "Download AspNet.Security.OAuth.Gitter from NuGet.org") | [](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 | [](https://www.nuget.org/packages/AspNet.Security.OAuth.Harvest/ "Download AspNet.Security.OAuth.Harvest from NuGet.org") | [](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) | [](https://www.nuget.org/packages/AspNet.Security.OAuth.HealthGraph/ "Download AspNet.Security.OAuth.HealthGraph from NuGet.org") | [](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
+ }
+ }
+ ]
+}