Cómo: Solicitar un token de ACS a través del protocolo WRAP de OAuth
Se aplica a
- Active Directory Access Control de Microsoft Azure (también conocido como Access Control Service o ACS)
Información general
Cuando las aplicaciones web y los servicios controlan la autenticación mediante ACS, el cliente debe obtener un token de seguridad emitido por ACS para iniciar sesión en la aplicación o el servicio. Para obtener este token emitido por ACS (token de salida), el cliente debe autenticarse directamente con ACS o enviar a ACS un token de seguridad emitido por su proveedor de identidades (token de entrada). ACS valida este token de seguridad de entrada, procesa las notificaciones de identidad de este token a través del motor de reglas de ACS, calcula las notificaciones de identidad de salida y emite un token de seguridad de salida.
En este tema se describen los métodos para solicitar un token de ACS a través del protocolo WRAP de OAuth. Todas las solicitudes de token a través del protocolo WRAP de OAuth se transmiten a través de SSL. ACS siempre emite un token web simple (SWT) a través del protocolo WRAP de OAuth, en respuesta a una solicitud de token con formato correcto. Todas las solicitudes de token a través del protocolo WRAP de OAuth se envían a ACS en un HTTP POST. Puede solicitar un token de ACS a través del protocolo WRAP de OAuth desde cualquier plataforma que pueda realizar una solicitud HTTPS FORM POST: .NET Framework, Windows Communication Foundation (WCF), Silverlight, ASP.NET, Java, Python, Ruby, PHP, Flash y otras plataformas.
En la tabla siguiente se enumeran tres métodos admitidos para solicitar un token SWT emitido por ACS a través del protocolo WRAP de OAuth.
Tres métodos para solicitar un token de ACS mediante el protocolo OAuth WRAP
Método de solicitud de token | Descripción |
---|---|
Solicitudes de token de contraseña |
Este método más sencillo requiere que el cliente envíe un nombre de usuario y una contraseña desde una identidad de servicio directamente a ACS a través del protocolo WRAP de OAuth para la autenticación. |
Solicitudes de token de SWT |
Este método requiere que el cliente envíe un token SWT que se pueda firmar con una clave simétrica de identidad de servicio o una clave simétrica del proveedor de identidades a ACS a través del protocolo WRAP de OAuth para la autenticación. |
Solicitudes de token de SAML |
Diseñado principalmente para la integración del Servicio de federación de Active Directory (AD FS) 2.0, el método del lenguaje de marcado de aserción de seguridad (SAML) requiere que el cliente envíe un token SAML firmado a ACS a través del protocolo OAuth WRAP para la autenticación. Este enfoque permite al cliente usar una identidad empresarial para autenticarse con ACS. |
Extremo emisor de token
Todas las solicitudes de token de ACS a través del protocolo WRAP de OAuth se dirigen a un punto de conexión de emisión de tokens de ACS. El URI de este punto de conexión depende del espacio de nombres Access Control. El espacio de nombres aparece como un prefijo de nombre DNS en un URI de solicitud de token. El resto del nombre del DNS es fijo, como la ruta de acceso. Por ejemplo, si desea solicitar un token desde el espacio de nombres Access Control denominado "mysnservice", puede dirigir una solicitud de token al siguiente URI: https://mysnservice.accesscontrol.windows.net/WRAPv0.9.
Solicitudes de token de contraseña
Con una solicitud de token de contraseña, un cliente puede enviar un nombre de usuario y una contraseña desde una identidad de servicio directamente a ACS a través del protocolo WRAP de OAuth para la autenticación. Esta es la manera más fácil de solicitar un token de ACS mediante el protocolo WRAP de OAuth. Aparte de establecer una conexión SSL, este enfoque no requiere ninguna capacidad de cifrado. En la práctica, es similar al modelo de usuario/contraseña que es frecuente en servicios web REST. Este tipo de solicitud de token es realmente un formulario HTTPS POST. Los parámetros de una solicitud de token de contraseña están codificados por formulario.
El siguiente es un ejemplo de un seguimiento de la conexión de una solicitud de texto simple a un espacio de nombres denominado "mysnservice".
POST /WRAPv0.9/ HTTP/1.1
Host: mysnservice.accesscontrol.windows.net
Content-Type: application/x-www-form-urlencoded
wrap_scope=http%3A%2F%2Fmysnservice.com%2Fservices%2F&
wrap_name=mysncustomer1&
wrap_password=5znwNTZDYC39dqhFOTDtnaikd1hiuRa4XaAj3Y9kJhQ%3D
En la tabla siguiente se proporcionan los nombres, descripciones y requisitos de valor de los parámetros que deben estar presentes en una solicitud de token de contraseña:
Nombre de parámetro | Descripción | Requisitos de valor |
---|---|---|
wrap_scope |
Hace coincidir la solicitud de token con un conjunto de reglas. Establezca el valor de este parámetro al valor del dominio de la aplicación del usuario de confianza. Puede obtener este valor (en el campo Dominio ) a través del Portal de administración de ACS seleccionando la aplicación de usuario de confianza adecuada en la página Aplicaciones de usuario de confianza. |
|
wrap_name |
Valida la clave del parámetro siguiente. Establezca el valor de este parámetro en el nombre de una identidad de servicio en el espacio de nombres Access Control. Puede obtener este valor (en el campo Nombre ) a través del Portal de administración de ACS seleccionando la identidad de servicio adecuada en la página Identidades de servicio. |
|
wrap_password |
Autentica la solicitud entrante. Establezca el valor de este parámetro en la contraseña de una identidad de servicio en el espacio de nombres Access Control. Puede obtener este valor (en el campo Contraseña de la página Editar credencial), a través del Portal de administración de ACS, seleccionando primero la identidad de servicio adecuada en la página Identidades de servicio y seleccionando la contraseña adecuada en la tabla Credenciales de la página Editar identidad del servicio . |
|
Los valores de estos parámetros deben estar codificados en url antes de enviar la solicitud a ACS. La aplicación web o el servicio pueden proporcionar el valor del wrap_scope al cliente, o el cliente puede decidir establecer el valor del parámetro wrap_scope en el URI de la aplicación web o el destino del recurso de servicio.
Las solicitudes de token de contraseña a través del protocolo WRAP de OAuth también pueden contener parámetros adicionales que ACS puede usar durante el proceso de cálculo de notificaciones de salida. Estos nombres de parámetros adicionales y los valores deben codificarse para URL y los valores no deben estar entre comillas.
El método de solicitud de token de contraseña es bastante sencillo con .
WebClient client = new WebClient();
client.BaseAddress = string.Format("https://mysnservice.accesscontrol.windows.net");
NameValueCollection values = new NameValueCollection();
values.Add("wrap_name", "mysncustomer1");
values.Add("wrap_password", "5znwNTZDYC39dqhFOTDtnaikd1hiuRa4XaAj3Y9kJhQ=");
values.Add("wrap_scope", "http://mysnservice.com/services");
// WebClient takes care of the URL Encoding
byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
// the raw response from ACS
string response = Encoding.UTF8.GetString(responseBytes);
Para obtener información sobre cómo desempaquetar el token de salida de ACS y enviarlo a la aplicación o servicio web, consulte Desencapsulado y envío del token a una aplicación web o servicio.
Solicitudes de token de SWT
También puede solicitar un token de ACS a través del protocolo WRAP de OAuth mediante un token SWT firmado por una clave simétrica. Todas las solicitudes de tokens de SWT se realizan a través de un formulario HTTPS POST. Los valores de parámetro de este método de solicitud de token están codificados para formulario.
El siguiente es un ejemplo de un seguimiento de la conexión de una solicitud de token de SWT en el espacio de nombres "mysnservice".
POST /WRAPv0.9/ HTTP/1.1
Host: mysnservice.accesscontrol.windows.net
Content-Type: application/x-www-form-urlencoded
wrap_scope=http%3A%2F%2Fmysnservice.com%2Fservices%2F&
wrap_assertion_format=SWT&
wrap_assertion=Issuer%3dmysncustomer1%26HMACSHA256%3db%252f%252bJFwbngGdufECFjQb8qhb9YH0e32Cf9ABMDZFiPPA%253d
Una solicitud de token de SWT debe tener los siguientes parámetros y valores:
Nombre de parámetro | Descripción | Requisitos de valor |
---|---|---|
wrap_scope |
Hace coincidir la solicitud de token con un conjunto de reglas. |
|
wrap_assertion |
Este es el token de entrada que se envía a ACS. |
|
wrap_assertion_format |
Este es el formato del token de entrada que se envía a ACS. |
SWT |
Como se muestra en el ejemplo siguiente, el código necesario para realizar una solicitud de token de SWT es similar al código necesario para realizar una solicitud de token de contraseña.
WebClient client = new WebClient();
client.BaseAddress = string.Format("https://mysnservice.accesscontrol.windows.net");
NameValueCollection values = new NameValueCollection();
// add the wrap_scope
values.Add("wrap_scope", "http://mysnservice.com/services");
// add the format
values.Add("wrap_assertion_format", "SWT");
// add the SWT
values.Add("wrap_assertion", "Issuer=mysncustomer1&HMACSHA256=b%2f%2bJFwbngGdufECFjQb8qhb9YH0e32Cf9ABMDZFiPPA%3d");
// WebClient takes care of the remaining URL Encoding
byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
// the raw response from ACS
string response = Encoding.UTF8.GetString(responseBytes);
Para obtener información sobre cómo desempaquetar la respuesta de ACS y enviarlo a su aplicación o servicio web, consulte Desencapsulado y envío del token a una aplicación web o servicio.
Creación de un token de SWT
Un token de SWT es un conjunto de pares clave/valor que están firmados con una clave de emisor (una clave simétrica). Un token SWT enviado a ACS en una solicitud de token SWT debe contener los parámetros Issuer y HMACSHA256 , así como parámetros adicionales, por ejemplo, ExpiresOn, Audience y otras notificaciones específicas del cliente. En la tabla siguiente se proporcionan los nombres y descripciones de los parámetros de token de SWT:
Nombre de parámetro | Descripción |
---|---|
Emisor |
En ACS, busca la clave que se usó para firmar el token. Si la firma es válida, este valor se usa para realizar el cálculo de la notificación de salida. Puede establecer este parámetro en el valor del dominio de un proveedor de identidades dentro del espacio de nombres de Access Control o el nombre de una identidad de servicio dentro del espacio de nombres de Access Control. Puede obtener este valor (en el campo Dominio del dominio de la página Editar proveedor de identidades ) mediante el Portal de administración de ACS; para ello, seleccione el proveedor de identidades adecuado en la página Proveedores de identidades. O bien, puede obtener este valor a través del servicio de administración de ACS: esta es la propiedad name del registro "Emisor" que se crea para cada proveedor de identidades. |
HMACSHA256 |
En ACS, valida la firma SWT y busca la clave del emisor denominada en el parámetro Issuer . La firma SWT se crea mediante la clave de firma simétrica asociada a una identidad de servicio o a un proveedor de identidades dentro del espacio de nombres de Access Control. |
Audiencia |
Si está presente, ACS usa este valor para asegurarse de que ACS es el destino previsto del token SWT. Esta es la dirección URL del espacio de nombres de Access Control, por ejemplo,https://contoso.accesscontrol.windows.net/ |
ExpiresOn |
Si está presente (en tiempo base), indica si el token ha caducado. Por ejemplo, el valor de este parámetro puede ser |
Notificaciones adicionales |
Si está presente, ACS usa estos parámetros para realizar el cálculo de notificaciones de salida. Cada tipo de notificación debe aparecer solo una vez. Varios valores de notificación del mismo tipo de notificación se deben concatenar con una "," (coma). Para obtener más información sobre la aserción de notificaciones en ACS, consulte Aserción de notificaciones a través del protocolo WRAP de OAuth. |
En el ejemplo de código siguiente se muestra cómo generar un token de SWT mediante . Contiene un tipo que genera tokens de SWT que contienen los parámetros Emisor y HMACSHA256.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
public class TokenFactory
{
string signingKey;
string issuer;
public TokenFactory(string issuer, string signingKey)
{
this.issuer = issuer;
this.signingKey = signingKey;
}
public string CreateToken()
{
StringBuilder builder = new StringBuilder();
// add the issuer name
builder.Append("Issuer=");
builder.Append(HttpUtility.UrlEncode(this.issuer));
string signature = this.GenerateSignature(builder.ToString(), this.signingKey);
builder.Append("&HMACSHA256=");
builder.Append(signature);
return builder.ToString();
}
private string GenerateSignature(string unsignedToken, string signingKey)
{
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(signingKey));
byte[] locallyGeneratedSignatureInBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken));
string locallyGeneratedSignature = HttpUtility.UrlEncode(Convert.ToBase64String(locallyGeneratedSignatureInBytes));
return locallyGeneratedSignature;
}
}
Solicitudes de token de SAML
El método de solicitud de token SAML está pensado principalmente para la integración de AD FS 2.0 y permite al cliente usar una identidad de empresa (Active Directory) para autenticarse con ACS. Con el método de solicitud de token SAML, puede enviar un token SAML 1.1 firmado o un token SAML 2.0 emitido por AD FS 2.0 (token de entrada) a ACS mediante el protocolo WRAP de OAuth.
ACS usa sus reglas para calcular las notificaciones de salida, las agrupa en un token de SWT (token de salida), lo firma y devuelve al cliente a través del protocolo OAuth WRAP.
Una solicitud de token de SAML debe tener los siguientes parámetros y valores:
Nombre de parámetro | Descripción | Requisitos de valor |
---|---|---|
wrap_scope |
Hace coincidir la solicitud de token con un conjunto de reglas. |
|
wrap_assertion |
Este es el token de entrada que se envía a ACS. |
|
wrap_assertion_format |
Este es el formato del token de entrada que se envía a ACS. |
SAML |
El siguiente es un ejemplo del código que se requiere para hacer una solicitud de token de SAML.
private static string SendSAMLTokenToACS(string samlToken)
{
try
{
WebClient client = new WebClient();
client.BaseAddress = string.Format("https://mysnservice.accesscontrol.windows.net");
NameValueCollection parameters = new NameValueCollection();
parameters.Add("wrap_assertion_format", "SAML");
parameters.Add("wrap_assertion", samlToken);
parameters.Add("wrap_scope", "http://mysnservice.com/services");
byte[] responseBytes = client.UploadValues("WRAPv0.9", parameters);
string response = Encoding.UTF8.GetString(responseBytes);
return response
.Split('&')
.Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase))
.Split('=')[1];
}
catch (WebException wex)
{
string value = new StreamReader(wex.Response.GetResponseStream()).ReadToEnd();
throw;
}
}
Para obtener información sobre cómo desempaquetar la respuesta de ACS y enviarla a su aplicación o servicio web, consulte Desencapsulado y envío del token a una aplicación web o servicio.
Aserción de notificaciones a través del protocolo OAuth WRAP
Para habilitar la compatibilidad con versiones anteriores con el comportamiento de la solicitud de token de ACS 1.0, ACS admite la capacidad de declarar notificaciones como parte de las solicitudes de token.
Registre la aplicación o servicio de confirmación como proveedor de identidad ACS.
La manera recomendada de hacerlo es registrar la aplicación o servicio de confirmación como proveedor de identidad ACS. A continuación, la aplicación o el servicio solicita un token de ACS mediante la presentación de un token SAML o SWT que contiene las notificaciones que quiere afirmar y este token se firma mediante una clave del proveedor de identidades almacenada en ACS. Por ejemplo, puede enviar una solicitud de token SAML con notificaciones aseridas a ACS a través del protocolo OAuth WRAP de AD FS 2.0 o cualquier servicio de token de seguridad (STS) personalizado que se compila mediante Windows Identity Foundation (WIF) y registrado en ACS como proveedor de identidades de WS-Federation.
Puede usar el Portal de administración de ACS para registrar un proveedor de identidades mediante WS-Federation metadatos, o bien puede usar el servicio de administración de ACS para establecer individualmente las propiedades, las direcciones y las claves del proveedor de identidades. (Por ejemplo, vea How to: Use ACS Management Service to Configure AD FS 2.0 as an Enterprise Identity Provider).) No es necesaria ninguna identidad de servicio en este método de afirmación de notificaciones en una solicitud de token. Este método es funcional a través de todos los protocolos compatibles con ACS.
Desempaquetar y enviar el token a una aplicación o servicio web
Si la solicitud de token se autentica correctamente, ACS devuelve dos parámetros codificados con formato: wrap_token y wrap_token_expires_in. Los valores de estos parámetros son el token de SWT real que el cliente puede usar para tener acceso a la aplicación web o servicio y la duración restante aproximada del token (en segundos), respectivamente.
Antes de enviar el token SWT a la aplicación web o al servicio, el cliente debe extraerlo y descodificarla de la dirección URL de la respuesta de ACS. Si la aplicación web o servicio requiere que el token se presente en el encabezado Authorization
de HTTP, el token debe ir precedido por el esquema WRAPv0.9
.
En el ejemplo de código siguiente se muestra cómo desempaquetar un token y el formato del encabezado Authorization
.
WebClient client = new WebClient();
client.BaseAddress = string.Format("https://mysnservice.accesscontrol.windows.net");
NameValueCollection values = new NameValueCollection();
values.Add("wrap_name", "mysncustomer1");
values.Add("wrap_password", "5znwNTZDYC39dqhFOTDtnaikd1hiuRa4XaAj3Y9kJhQ=");
values.Add("wrap_scope", "http://mysnservice.com/services");
// WebClient takes care of the URL Encoding
byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
// the raw response from ACS
string response = Encoding.UTF8.GetString(responseBytes);
string token = response
.Split('&')
.Single(value => value.StartsWith("wrap_token=", StringComparison.OrdinalIgnoreCase))
.Split('=')[1];
string.Format("WRAP access_token=\"{0}\"", HttpUtility.UrlDecode(token));
Códigos de error de ACS y descripciones
ACS devuelve errores cuando no puede satisfacer una solicitud de token. De acuerdo con el diseño REST, el error contiene un código de respuesta HTTP. En muchos casos, los errores de ACS también contienen un SubCode
y Detail
que proporcionan contexto sobre lo que ha fallado. El formato de error es: Error:Code:httpStatus:<Sub-Code:<code>:D etail:<message>>. El Content-Type
de un error siempre es texto sin formato.
HTTP/1.1 401 Access Forbidden
Content-Type: text/plain; charset=us-ascii
Error:Code:401:SubCode:T0:Detail:ACS50009: SWT token is invalid. :TraceID:<trace id value>:TimeStamp:<timestamp value>
Para obtener más información sobre los códigos de error de ACS, consulte Códigos de error de ACS.
Al depurar o recuperarse de un error devuelto por ACS, a menudo es necesario leer el cuerpo de la respuesta. En el ejemplo de código siguiente se muestra cómo leer el mensaje de error de un objeto WebException .
try
{
WebClient client = new WebClient();
client.BaseAddress = string.Format("https://mysnservice.accesscontrol.windows.net");
NameValueCollection values = new NameValueCollection();
values.Add("wrap_name", "mysncustomer1");
values.Add("wrap_password", "5znwNTZDYC39dqhFOTDtnaikd1hiuRa4XaAj3Y9kJhQ=");
values.Add("wrap_scope", "http://mysnservice.com/services");
// WebClient takes care of the URL Encoding
byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
// the raw response from ACS
string response = Encoding.UTF8.GetString(responseBytes);
string token = response
.Split('&')
.Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase))
.Split('=')[1];
}
catch (WebException wex)
{
if (wex.Response != null)
{
// the response Stream contains the error message
StreamReader reader = new StreamReader(wex.Response.GetResponseStream());
string message = reader.ReadToEnd();
}
// Throw as appropriate
}