Skip to content

Commit ec5cef7

Browse files
committed
feat(auth): add login and refresh mutation
BREAKING CHANGE: Older rest endpoint to login and refresh removed
1 parent 755c65b commit ec5cef7

File tree

18 files changed

+197
-219
lines changed

18 files changed

+197
-219
lines changed

Micro.Auth.Api/Authentication/Exceptions/BadBasicAuthorizationDataException.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.

Micro.Auth.Api/Authentication/SessionController.cs

Lines changed: 0 additions & 150 deletions
This file was deleted.

Micro.Auth.Api/Authentication/ViewModels/JwtRefreshViewModels.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace Micro.Auth.Api.GraphQL.Extensions.Exceptions
4+
{
5+
public class InvalidTokenTypeException : Exception
6+
{
7+
public InvalidTokenTypeException(string expectedType) : base($"{expectedType} token not found")
8+
{
9+
}
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace Micro.Auth.Api.GraphQL.Extensions.Exceptions
4+
{
5+
public class MissingHeaderException : Exception
6+
{
7+
public MissingHeaderException(string headerName) : base($"Missing {headerName} header")
8+
{
9+
}
10+
}
11+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Micro.Auth.Api.Internal.UserData.Extensions;
2+
using Micro.Auth.Business.Sessions;
3+
using Microsoft.AspNetCore.Http;
4+
5+
namespace Micro.Auth.Api.GraphQL.Extensions
6+
{
7+
public static class LoginRequestExtension
8+
{
9+
public static LoginRequest GetLoginRequest(this IHttpContextAccessor httpContextAccessor)
10+
{
11+
var (login, password) = httpContextAccessor.MustGetBasicToken();
12+
return new LoginRequest
13+
{
14+
Login = login,
15+
Password = password,
16+
IpAddress = httpContextAccessor.GetIpAddress(),
17+
UserAgent = httpContextAccessor.GetUserAgent(),
18+
Location = httpContextAccessor.GetRoughLocation()
19+
};
20+
}
21+
}
22+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.Text;
3+
using Micro.Auth.Api.GraphQL.Extensions.Exceptions;
4+
using Microsoft.AspNetCore.Http;
5+
using Microsoft.Extensions.Primitives;
6+
7+
namespace Micro.Auth.Api.GraphQL.Extensions
8+
{
9+
public static class Tokens
10+
{
11+
public static string MustGetBearerToken(this IHttpContextAccessor httpContextAccessor)
12+
{
13+
var headerValue = httpContextAccessor.MustGetAuthHeader();
14+
if (!headerValue.StartsWith("Bearer "))
15+
{
16+
throw new InvalidTokenTypeException("Bearer");
17+
}
18+
return headerValue.Substring("Bearer ".Length).Trim();
19+
}
20+
21+
private static string MustGetAuthHeader(this IHttpContextAccessor httpContextAccessor)
22+
{
23+
var header = StringValues.Empty;
24+
var exists = httpContextAccessor.HttpContext?.Request.Headers.TryGetValue("Authorization", out header);
25+
if (exists == false || header.ToString() == "")
26+
{
27+
throw new MissingHeaderException("Authorization");
28+
}
29+
30+
return header.ToString();
31+
}
32+
33+
public static (string, string) MustGetBasicToken(this IHttpContextAccessor httpContextAccessor)
34+
{
35+
try
36+
{
37+
var headerValue = httpContextAccessor.MustGetAuthHeader();
38+
if (!headerValue.StartsWith("Basic "))
39+
{
40+
throw new InvalidTokenTypeException("Basic");
41+
}
42+
43+
var token = headerValue.Substring("Basic ".Length).Trim();
44+
var parts = Encoding.UTF8.GetString(Convert.FromBase64String(token)).Split(":");
45+
return (parts[0], parts[1]);
46+
}
47+
catch (Exception e)
48+
{
49+
throw new InvalidTokenTypeException(e.Message);
50+
}
51+
}
52+
}
53+
}

Micro.Auth.Api/GraphQL/Mutation.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
using GraphQL;
22
using GraphQL.Types;
33
using Micro.Auth.Api.GraphQL.Directives.Extensions;
4+
using Micro.Auth.Api.GraphQL.Extensions;
45
using Micro.Auth.Api.GraphQL.Inputs;
56
using Micro.Auth.Api.GraphQL.Types;
67
using Micro.Auth.Api.Internal.UserData.Extensions;
78
using Micro.Auth.Business.Common;
89
using Micro.Auth.Business.EmailVerification;
910
using Micro.Auth.Business.PasswordManager;
11+
using Micro.Auth.Business.Sessions;
1012
using Micro.Auth.Business.Users;
1113
using Microsoft.AspNetCore.Http;
1214

1315
namespace Micro.Auth.Api.GraphQL
1416
{
1517
public class Mutation : ObjectGraphType
1618
{
17-
public Mutation(IUserService userService, IPasswordManager passwordManager, IEmailVerificationService verification, IHttpContextAccessor contextAccessor)
19+
public Mutation(IUserService userService, IPasswordManager passwordManager, IEmailVerificationService verification, ISessionService sessionService, IHttpContextAccessor contextAccessor)
1820
{
1921
FieldAsync<NonNullGraphType<UserType>, User>("register",
2022
arguments: new QueryArguments(RegisterInputType.BuildArgument()),
2123
resolve: x => userService.Create(x.GetArgument<RegisterInput>("input")));
2224

25+
FieldAsync<NonNullGraphType<StringGraphType>, string>("refreshToken",
26+
resolve: x => sessionService.Refresh(contextAccessor.MustGetBearerToken()));
27+
28+
FieldAsync<NonNullGraphType<TokensType>, LoginSuccessResponse>("login",
29+
resolve: x => sessionService.Login(contextAccessor.GetLoginRequest()));
30+
2331
FieldAsync<NonNullGraphType<UserType>, User>("verifyEmail",
2432
arguments: new QueryArguments(VerifyEmailInputType.BuildArgument()),
2533
resolve: x => verification.ConfirmEmail(x.GetArgument<VerifyEmailInput>("input")));
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Micro.Auth.Business.Sessions;
2+
3+
namespace Micro.Auth.Api.GraphQL.Types
4+
{
5+
public sealed class TokensType : Micro.GraphQL.Federation.ObjectGraphType<LoginSuccessResponse>
6+
{
7+
public TokensType()
8+
{
9+
Name = "Token";
10+
Field("jwt", x => x.Jwt).Description("JWT");
11+
Field("refreshToken", x => x.RefreshToken, true)
12+
.Description("Once JWT expires, use this token to create a new session");
13+
}
14+
}
15+
}

Micro.Auth.Api/Internal/StartupExtensions/GraphQl.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public static void ConfigureGraphQl(this IServiceCollection services)
2727
services.AddTransient<UserType>();
2828
services.AddTransient<AvailabilityResultType>();
2929
services.AddTransient<ResultType>();
30+
services.AddTransient<TokensType>();
3031
services.AddTransient<RegisterInputType>();
3132
services.AddTransient<RefreshTokenType>();
3233
services.AddTransient<ChangePasswordInput>();

0 commit comments

Comments
 (0)