В настоящее время у меня есть пара служб на основе OWIN, каждая из которых использует аутентификацию OAuth против одного и того же набора пользователей. Я намерен изолировать сервер авторизации (т.е. Конечную точку маркера) и каким-то образом настроить оба моих сервиса для принятия этого токена. Я предполагаю, что это потребует некоторой конфигурации всех моих сервисов, чтобы этот токен был расшифрован во всех соответствующих сервисах. Возможно ли это?
Использование билетов Oauth через несколько сервисов?
Ответ 1
Второе программное обеспечение сервера авторизации Catalana OAuth2 не предназначалось для этого сценария (главным образом потому, что его зависимость от машинного ключа для проверки токена).
Если вы хотите централизовать генерацию маркера, вам следует изучить сервер авторизации OAuth2, который был разработан для этого. Thinktecture AuthorizationServer - это сервер с открытым исходным кодом, который делает это: http://thinktecture.github.io/Thinktecture.AuthorizationServer/
Ответ 2
После разговора с Броком Алленом в комментариях к исходному сообщению я не могу гарантировать, что это хорошее/безопасное решение, но это код, который я использовал. (Примечание: версия этого кода доступна как пакет nuget.)
Я создал реализацию IDataProtector, которая использует AES:
internal class AesDataProtectorProvider : IDataProtector
{
// Fields
private byte[] key;
// Constructors
public AesDataProtectorProvider(string key)
{
using (var sha1 = new SHA256Managed())
{
this.key = sha1.ComputeHash(Encoding.UTF8.GetBytes(key));
}
}
// IDataProtector Methods
public byte[] Protect(byte[] data)
{
byte[] dataHash;
using (var sha = new SHA256Managed())
{
dataHash = sha.ComputeHash(data);
}
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = this.key;
aesAlg.GenerateIV();
using (var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV))
using (var msEncrypt = new MemoryStream())
{
msEncrypt.Write(aesAlg.IV, 0, 16);
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var bwEncrypt = new BinaryWriter(csEncrypt))
{
bwEncrypt.Write(dataHash);
bwEncrypt.Write(data.Length);
bwEncrypt.Write(data);
}
var protectedData = msEncrypt.ToArray();
return protectedData;
}
}
}
public byte[] Unprotect(byte[] protectedData)
{
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = this.key;
using (var msDecrypt = new MemoryStream(protectedData))
{
byte[] iv = new byte[16];
msDecrypt.Read(iv, 0, 16);
aesAlg.IV = iv;
using (var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (var brDecrypt = new BinaryReader(csDecrypt))
{
var signature = brDecrypt.ReadBytes(32);
var len = brDecrypt.ReadInt32();
var data = brDecrypt.ReadBytes(len);
byte[] dataHash;
using (var sha = new SHA256Managed())
{
dataHash = sha.ComputeHash(data);
}
if (!dataHash.SequenceEqual(signature))
throw new SecurityException("Signature does not match the computed hash");
return data;
}
}
}
}
}
И затем использовал это в реализации ISecureDataFormat следующим образом:
public class SecureTokenFormatter : ISecureDataFormat<AuthenticationTicket>
{
// Fields
private TicketSerializer serializer;
private IDataProtector protector;
private ITextEncoder encoder;
// Constructors
public SecureTokenFormatter(string key)
{
this.serializer = new TicketSerializer();
this.protector = new AesDataProtectorProvider(key);
this.encoder = TextEncodings.Base64Url;
}
// ISecureDataFormat<AuthenticationTicket> Members
public string Protect(AuthenticationTicket ticket)
{
var ticketData = this.serializer.Serialize(ticket);
var protectedData = this.protector.Protect(ticketData);
var protectedString = this.encoder.Encode(protectedData);
return protectedString;
}
public AuthenticationTicket Unprotect(string text)
{
var protectedData = this.encoder.Decode(text);
var ticketData = this.protector.Unprotect(protectedData);
var ticket = this.serializer.Deserialize(ticketData);
return ticket;
}
}
Параметр "ключ" в конструкторе может быть установлен на одно и то же значение для нескольких служб, и все они смогут расшифровать ( "снять защиту" ) и использовать билет.
Ответ 3
Я знаю, что это старый вопрос, но у меня был аналогичный вариант использования. В соответствии с документами OWIN OAuth использует машинный ключ для защиты данных. Поскольку вы контролируете все экземпляры, я полагаю, что просто настройка машинного ключа в веб-конфигурации будет работать.
Ответ 4
Вы можете использовать этот пакет nuget https://www.nuget.org/packages/Owin.Security.AesDataProtectorProvider/
Он содержит метод расширения для IAppBuilder, который позволяет вам настроить собственный ключ
appBuilder.UseAesDataProtectorProvider(key);