ADFS 3.0 мобильное приложение Cordova API

#cordova #adfs #adal

#кордова #adfs #adal

Вопрос:

Наше приложение Cordova должно запрашивать токены безопасности из локальной ADFS (3.0). Затем используйте токен для подключения к веб-службам. Все примеры, которые я нашел, говорят, что это возможно, но только демонстрируют, как это сделать с помощью Azure.

Где я могу найти подробную информацию по настройке ADFS 3.0? Существует ли лучший подход?

Ответ №1:

Сегодня я решил эту проблему. Вот рабочий пример. Он должен работать для всех мобильных приложений, а не только для Cordova.

         string adfsHost = "https://<Your ADFS FQDN>";
        string sendTo = $"{adfsHost}/adfs/services/trust/13/usernamemixed";
        string _username = "<Your Domain\<Your username>"; 
        string _password = "<Your password>";
        string applyTo = "<Your Resource URI>";
        string tokenType = "urn:ietf:params:oauth:token-type:jwt";

        string soapMessage = $@"
            <s:Envelope xmlns:s=""http://www.w3.org/2003/05/soap-envelope""
                        xmlns:a=""http://www.w3.org/2005/08/addressing""
                        xmlns:u=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"">
              <s:Header>
                <a:Action s:mustUnderstand=""1"">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>
                <a:To s:mustUnderstand=""1"">{sendTo}</a:To>
                <o:Security s:mustUnderstand=""1"" xmlns:o=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"">
                  <o:UsernameToken u:Id="" uuid-00000000-0000-0000-0000-000000000000-0"">
                    <o:Username>{_username}</o:Username>
                    <o:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"">{_password}</o:Password>
                  </o:UsernameToken>
                </o:Security>
              </s:Header>
              <s:Body>
                <trust:RequestSecurityToken xmlns:trust=""http://docs.oasis-open.org/ws-sx/ws-trust/200512"">
                  <wsp:AppliesTo xmlns:wsp=""http://schemas.xmlsoap.org/ws/2004/09/policy"">
                    <a:EndpointReference>
                      <a:Address>{applyTo}</a:Address>
                    </a:EndpointReference>
                  </wsp:AppliesTo>
                  <trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
                  <trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
                  <trust:TokenType>{tokenType}</trust:TokenType>
                </trust:RequestSecurityToken>
              </s:Body>
            </s:Envelope>
        ";

        XmlDocument xml = new XmlDocument();
        xml.LoadXml(soapMessage);

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(sendTo);

        request.ContentType = "application/soap xml; charset=utf-8";
        request.Method = "POST";
        request.Accept = "application/json";

        var stream = request.GetRequestStream();
        xml.Save(stream);

        WebResponse response = request.GetResponse();
        string strResponse;
        using (Stream responseStream = response.GetResponseStream())
        {
            using (StreamReader sr = new StreamReader(responseStream, System.Text.Encoding.ASCII))
            {
                strResponse = sr.ReadToEnd();
            }
        }

        JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();

        XmlDocument xml2 = new XmlDocument();
        xml2.LoadXml(strResponse);

        XmlNode node = xml2.SelectSingleNode("//*[@ValueType='urn:ietf:params:oauth:token-type:jwt']");
        XmlReader reader = new XmlNodeReader(node);
        JwtSecurityToken token = (JwtSecurityToken)handler.ReadToken(reader);

        string encryptedToken = token.RawData;
  

Код имитирует получение учетных данных пользователя из мобильного приложения вверху. Затем он устанавливает остальные значения, необходимые для вызова ADFS 3.0. Значения вставляются в конверт SOAP с использованием интерполяции строк.

Затем он создает веб-запрос. Затем он добавляет к запросу конверт SOAP и вызывает конечную точку ADFS. Вы должны получить ответ SOAP, содержащий BinarySecurityToken и код состояния 200.

Токен JWT заключен в BinarySecurityToken. Чтобы извлечь его, вы должны выбрать wsse:BinarySecurityToken, который его содержит, и использовать JwtSecurityTokenHandler.ReadToken(), чтобы извлечь его. Затем вы можете отправить токен в мобильное приложение, где его можно использовать для выполнения запросов API.

Вы могли бы использовать тот же подход для вызова ADFS непосредственно с мобильного телефона, но я предпочитаю делать это на стороне API.

Кроме того, я настоятельно рекомендую вам НЕ использовать самозаверяющие сертификаты. ИМХО, многие взаимодействия с ADFS просто не будут работать. Просто избавьте себя от головной боли.