Autenticar la llamada WCF a ADFS a través del Proxy de aplicación web (WAP)

0

Actualmente autenticamos las llamadas de WCF A un servicio a través de ADFS, mediante el siguiente procedimiento:

En primer lugar, obtenemos un token SAML de ADFS

using (var factory = new WSTrustChannelFactory(
   new UserNameWSTrustBinding(System.ServiceModel.SecurityMode.TransportWithMessageCredential),
   new System.ServiceModel.EndpointAddress(new Uri(_aDFSUsernameMixedUri))))
    {
        System.IdentityModel.Configuration.SecurityTokenServiceConfiguration serviceConfig = new System.IdentityModel.Configuration.SecurityTokenServiceConfiguration();
        factory.Credentials.UserName.UserName = _apiUser;
        factory.Credentials.UserName.Password = _apiPassword;
        factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = serviceConfig.CertificateValidationMode;
        factory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13;
        WSTrustChannel channel = null;
        try
        {
            var rst = new RequestSecurityToken
            {
                RequestType = WSTrust13Constants.RequestTypes.Issue,
                AppliesTo = new System.ServiceModel.EndpointAddress(_endpointUri),
                TokenType = "urn:oasis:names:tc:SAML:2.0:assertion",
                //KeyType = KeyTypes.Symmetric
                KeyType = KeyTypes.Bearer

            };

            var token = factory.CreateChannel().Issue(rst) as System.IdentityModel.Tokens.GenericXmlSecurityToken;

Utilizamos el punto final / adfs / services / trust / 13 / usernamemixed (variable _aDFSUsernameMixedUri). Este punto final es proxy habilitado.

En segundo lugar, usamos este token SAML para contactar con nuestro servicio:

using (HttpClient httpClient = new HttpClient() { BaseAddress = baseAddress })
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SAML", saml);
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            string jsonString = JsonConvert.SerializeObject(model);
            HttpResponseMessage response = await httpClient.PostAsync(Url, new StringContent(jsonString, Encoding.UTF8, "application/json"));
            return response;

        }

Vale la pena mencionar que el servicio solo acepta solicitudes autenticadas, y leerá los detalles de autorización del token SAML (que está firmado y encriptado). Así es como se asegura el servicio.

Ahora queremos proteger nuestro servidor ADFS mediante el uso de un Proxy ADFS (Proxy de aplicación web). La llamada a ADFS para el token SAML aún funciona y devuelve un token SAML. Sin embargo, el segundo paso falla . HTTPRequest está bloqueado por el servidor proxy de ADFS y redirige la llamada a la página de inicio de sesión de ADFS , que, por supuesto, no es lo que quiero.

Ya he intentado configurar passiveRedirectEnabled="false", pero esto no ayuda. ¿Alguna idea de dónde debo colocar el token SAML en la solicitud HTTP para que el proxy sepa que se trata de una solicitud autenticada?

ACTUALIZACIÓN

El Proxy ADFS utiliza un EdgeAccessCookie para decidir si redirige o no la solicitud al servidor ADFS. En caso de que pudiera agregar este EdgeAccessCookie a la solicitud, el proxy probablemente dejaría de bloquear la solicitud. ¿Cómo puedo recuperar este EdgeAccessCookie en una solicitud de WCF?

    
pregunta Michael 11.08.2014 - 17:48
fuente

2 respuestas

1

El proxy de aplicación web usa un token de autorización para decidir si configura EdgeAccessCookie o no. Si puede solicitar el token de autorización y colocarlo en la URL de su HTTPRequest, el WAP le permitirá pasar. Fragmentos de código:

        List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
        postData.Add(new KeyValuePair<string, string>("UserName", username));
        postData.Add(new KeyValuePair<string, string>("Password", pw));
        postData.Add(new KeyValuePair<string, string>("AuthMethod", "FormsAuthentication"));
        HttpContent content = new FormUrlEncodedContent(postData);

        WebRequestHandler webRequestHandler = new WebRequestHandler();
        webRequestHandler.AllowAutoRedirect = true;
        webRequestHandler.MaxAutomaticRedirections = 1;

        HttpResponseMessage response;
        using (HttpClient client = new HttpClient(webRequestHandler))
        {
            response = client.PostAsync(https://FQDNADFS/adfs/ls?version=1.0&action=signin&realm=urn:AppProxy:com&appRealm=REALMOFAPI&returnUrl=RETURNURL&RedirectToIdentityProvider=IDENTITYPROVIDER, content).Result;
        }

        authToken = HttpUtility.ParseQueryString(response.Headers.Location.Query)["authToken"];
        return authToken;

El fragmento de código anterior le dará el código de autorización, que debe incluir en la URL de su solicitud HTTP:

HttpResponseMessage response = await httpClient.PostAsync(Url + "/?authToken=" + authToken, new StringContent(jsonString, Encoding.UTF8, "application/json"));

En combinación con el código de mi pregunta (sin cambios), la WebAPI está protegida por el WAP. Buena suerte.

    
respondido por el Michael 19.08.2014 - 16:05
fuente
0

¿Cómo es exactamente el segundo paso bloqueado por el proxy de ADFS? El proxy solo debe bloquear las llamadas de ADFS, no las llamadas a su servicio. Dado que sus llamadas para obtener el token funcionan correctamente, yo diría que la configuración funciona como debería hacerlo con ADFS.

Donde las cosas se complican es en la configuración del servicio que estás protegiendo. ¿Por casualidad ejecutaste tu servicio a través de una de las aplicaciones fedutil en Visual Studio al reconfigurar el proxy ADFS? ¿Se pegó un bloque de autorización pasivo en el web.config por lo que todas las solicitudes deben ser autorizadas, en lugar de dejar que el servicio lo maneje?

Lo que debe hacer es rastrear el origen de la respuesta de redirección. Nada en el servicio debe ser forzado, ya que la base del servicio (generalmente) sabe mejor. Algunos de los culpables habituales son el FormsAuthenticationModule , SessionAuthenticationModule + WSFederationAuthenticationModule , etc.

    
respondido por el Steve 11.08.2014 - 18:26
fuente

Lea otras preguntas en las etiquetas