1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-25 12:45:18 +01:00

Revert device id in jwt token and moved to reading from header. Added clear token by identifier API/repo/sproc so that token can be cleared after logout.

This commit is contained in:
Kyle Spearrin 2016-08-06 15:15:11 -04:00
parent f07e9e9dd0
commit da56901d17
7 changed files with 40 additions and 28 deletions

View File

@ -107,22 +107,12 @@ namespace Bit.Api.Controllers
return response; return response;
} }
[AllowAnonymous]
[HttpPut("identifier/{identifier}/clear-token")] [HttpPut("identifier/{identifier}/clear-token")]
[HttpPost("identifier/{identifier}/clear-token")] [HttpPost("identifier/{identifier}/clear-token")]
public async Task<DeviceResponseModel> PutClearToken(string identifier) public async Task PutClearToken(string identifier)
{ {
var device = await _deviceRepository.GetByIdentifierAsync(identifier, new Guid(_userManager.GetUserId(User))); await _deviceRepository.ClearPushTokenByIdentifierAsync(identifier);
if(device == null)
{
await Task.Delay(2000);
throw new NotFoundException();
}
device.PushToken = null;
await _deviceService.SaveAsync(device);
var response = new DeviceResponseModel(device);
return response;
} }
[HttpDelete("{id}")] [HttpDelete("{id}")]

View File

@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Bit.Core.Domains; using Bit.Core.Domains;
using System.Linq;
namespace Bit.Core.Identity namespace Bit.Core.Identity
{ {
@ -38,10 +37,9 @@ namespace Bit.Core.Identity
// register the current context user // register the current context user
var currentContext = context.HttpContext.RequestServices.GetRequiredService<CurrentContext>(); var currentContext = context.HttpContext.RequestServices.GetRequiredService<CurrentContext>();
currentContext.User = user; currentContext.User = user;
var deviceIdentifierClaim = context.Ticket.Principal.Claims.SingleOrDefault(c => c.Type == "DeviceIdentifier"); if(context.HttpContext.Request.Headers.ContainsKey("Device-Identifier"))
if(deviceIdentifierClaim != null)
{ {
currentContext.DeviceIdentifier = deviceIdentifierClaim.Value; currentContext.DeviceIdentifier = context.HttpContext.Request.Headers["Device-Identifier"];
} }
} }

View File

@ -68,7 +68,7 @@ namespace Bit.Core.Identity
if(await UserManager.CheckPasswordAsync(user, password)) if(await UserManager.CheckPasswordAsync(user, password))
{ {
var result = await SignInOrTwoFactorAsync(user, device); var result = await SignInOrTwoFactorAsync(user);
if(result.Succeeded && device != null) if(result.Succeeded && device != null)
{ {
var existingDevice = await _deviceRepository.GetByIdentifierAsync(device.Identifier, user.Id); var existingDevice = await _deviceRepository.GetByIdentifierAsync(device.Identifier, user.Id);
@ -105,7 +105,7 @@ namespace Bit.Core.Identity
if(await UserManager.VerifyTwoFactorTokenAsync(user, provider, code)) if(await UserManager.VerifyTwoFactorTokenAsync(user, provider, code))
{ {
var token = await SignInAsync(user, false, device); var token = await SignInAsync(user, false);
var success = JwtBearerSignInResult.Success; var success = JwtBearerSignInResult.Success;
success.Token = token; success.Token = token;
@ -127,7 +127,7 @@ namespace Bit.Core.Identity
return JwtBearerSignInResult.Failed; return JwtBearerSignInResult.Failed;
} }
private async Task<string> SignInAsync(User user, bool twoFactor, Device device) private async Task<string> SignInAsync(User user, bool twoFactor)
{ {
var handler = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler(); var handler = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler();
@ -150,11 +150,6 @@ namespace Bit.Core.Identity
} }
} }
if(device != null && !string.IsNullOrWhiteSpace(device.Identifier))
{
userPrincipal.Identities.First().AddClaim(new Claim("DeviceIdentifier", device.Identifier));
}
var descriptor = new SecurityTokenDescriptor var descriptor = new SecurityTokenDescriptor
{ {
Issuer = JwtIdentityOptions.Issuer, Issuer = JwtIdentityOptions.Issuer,
@ -169,13 +164,13 @@ namespace Bit.Core.Identity
return handler.WriteToken(securityToken); return handler.WriteToken(securityToken);
} }
private async Task<JwtBearerSignInResult> SignInOrTwoFactorAsync(User user, Device device) private async Task<JwtBearerSignInResult> SignInOrTwoFactorAsync(User user)
{ {
if(UserManager.SupportsUserTwoFactor && if(UserManager.SupportsUserTwoFactor &&
await UserManager.GetTwoFactorEnabledAsync(user) && await UserManager.GetTwoFactorEnabledAsync(user) &&
(await UserManager.GetValidTwoFactorProvidersAsync(user)).Count > 0) (await UserManager.GetValidTwoFactorProvidersAsync(user)).Count > 0)
{ {
var twoFactorToken = await SignInAsync(user, true, device); var twoFactorToken = await SignInAsync(user, true);
var twoFactorResult = JwtBearerSignInResult.TwoFactorRequired; var twoFactorResult = JwtBearerSignInResult.TwoFactorRequired;
twoFactorResult.Token = twoFactorToken; twoFactorResult.Token = twoFactorToken;
@ -184,7 +179,7 @@ namespace Bit.Core.Identity
return twoFactorResult; return twoFactorResult;
} }
var token = await SignInAsync(user, false, device); var token = await SignInAsync(user, false);
var result = JwtBearerSignInResult.Success; var result = JwtBearerSignInResult.Success;
result.Token = token; result.Token = token;

View File

@ -10,5 +10,6 @@ namespace Bit.Core.Repositories
Task<Device> GetByIdAsync(Guid id, Guid userId); Task<Device> GetByIdAsync(Guid id, Guid userId);
Task<Device> GetByIdentifierAsync(string identifier, Guid userId); Task<Device> GetByIdentifierAsync(string identifier, Guid userId);
Task<ICollection<Device>> GetManyByUserIdAsync(Guid userId); Task<ICollection<Device>> GetManyByUserIdAsync(Guid userId);
Task ClearPushTokenByIdentifierAsync(string identifier);
} }
} }

View File

@ -59,5 +59,19 @@ namespace Bit.Core.Repositories.SqlServer
return results.ToList(); return results.ToList();
} }
} }
public async Task ClearPushTokenByIdentifierAsync(string identifier)
{
using(var connection = new SqlConnection(ConnectionString))
{
await connection.ExecuteAsync(
$"[{Schema}].[{Table}_ClearPushTokenByIdentifier]",
new
{
Identifier = identifier
},
commandType: CommandType.StoredProcedure);
}
}
} }
} }

View File

@ -93,5 +93,6 @@
<Build Include="dbo\Stored Procedures\Device_ReadByIdentifierUserId.sql" /> <Build Include="dbo\Stored Procedures\Device_ReadByIdentifierUserId.sql" />
<Build Include="dbo\Stored Procedures\Cipher_ReadByUserId.sql" /> <Build Include="dbo\Stored Procedures\Cipher_ReadByUserId.sql" />
<Build Include="dbo\Stored Procedures\User_UpdateEmailPassword.sql" /> <Build Include="dbo\Stored Procedures\User_UpdateEmailPassword.sql" />
<Build Include="dbo\Stored Procedures\Device_ClearPushTokenByIdentifier.sql" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,13 @@
CREATE PROCEDURE [dbo].[Device_ClearPushTokenByIdentifier]
@Identifier NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[Device]
SET
[Identifier] = NULL
WHERE
[Identifier] = @Identifier
END