Aracılığıyla paylaş


Kimlik sağlayıcıları ara sunucusu

Bu belgede, OAuth2 protokollerini kullanan özel veya gelişmiş kimlik sağlayıcılarıyla etkileşim kurmak için bir ara sunucu oluşturma açıklanmaktadır.

Bot Framework, kullanıcıların OAuth2 protokolunu kullanan çeşitli kimlik sağlayıcılarını kullanarak oturum açmasına olanak tanır. Ancak kimlik sağlayıcıları, daha gelişmiş özellikler veya alternatif oturum açma seçenekleri sunarak çekirdek OAuth2 protokolünden sapabilir. Böyle durumlarda, size uygun bir bağlantı ayarı yapılandırması bulamayabilirsiniz. Olası bir çözüm aşağıdakileri yapmaktır:

  1. Bot Framework belirteç hizmeti ile daha özelleştirilmiş veya gelişmiş kimlik sağlayıcısı arasında bulunan bir OAuth2 sağlayıcı proxy'si yazın.
  2. Bağlantı ayarını bu proxy'yi çağıracak şekilde yapılandırın ve bu proxy'nin özel veya gelişmiş kimlik sağlayıcısına çağrı yapmasını sağlayın. Ara sunucu, Bot Framework belirteç hizmetinin beklediğine uymalarını sağlamak için yanıtları eşleyebilir veya dönüştürebilir.

OAuth2 Proxy Hizmeti

OAuth2 Proxy Hizmeti oluşturmak için, biri yetkilendirme, diğeri belirteç almak için olmak üzere iki OAuth2 API'si olan bir REST hizmeti uygulamanız gerekir. Aşağıda, bu yöntemlerin her birinin C# örneğini ve özel veya gelişmiş bir kimlik sağlayıcısını çağırmak için bu yöntemlerde neler yapabileceğinizi bulacaksınız.

API'leri yetkilendirme

Yetkilendirme API'si, çağıranı yetkileyen, bir kod özelliği oluşturan ve yeniden yönlendirme URI'sine yönlendiren bir HTTP GET'tir .

[HttpGet("authorize")]
public ActionResult Authorize(
    string response_type, 
    string client_id, 
    string state, 
    string redirect_uri, 
    string scope = null)
{
    // validate parameters
    if (string.IsNullOrEmpty(state))
    {
        return BadRequest("Authorize request missing parameter 'state'");
    }

    if (string.IsNullOrEmpty(redirect_uri))
    {
        return BadRequest("Authorize request missing parameter 'redirect_uri'");
    }

    // redirect to an external identity provider, 
    // or for this sample, generate a code and token pair and redirect to the redirect_uri

    var code = Guid.NewGuid().ToString("n");
    var token = Guid.NewGuid().ToString("n");
    _tokens.AddOrUpdate(code, token, (c, t) => token);

    return Redirect($"{redirect_uri}?code={code}&state={state}");
}

Belirteç API'si

Belirteç API'si, Bot Framework belirteç hizmeti tarafından çağrılan bir HTTP POST'tır . Bot Framework belirteç hizmeti, isteğin gövdesinde ve'yi client_secret gönderirclient_id. Bu değerler doğrulanmalı ve/veya özel veya gelişmiş kimlik sağlayıcısına geçirilmelidir. Bu çağrıya verilen yanıt, belirtecin ve süre sonu değerini içeren access_token bir JSON nesnesidir (diğer tüm değerler yoksayılır). Kimlik sağlayıcınız bunun yerine döndürmek istediğiniz bir veya başka bir id_token değer döndürürse, geri dönmeden önce bunu access_token yanıtınızın özelliğiyle eşlemeniz yeterlidir.

[HttpPost("token")]
public async Task<ActionResult> Token()
{
    string body;

    using (var reader = new StreamReader(Request.Body))
    {
        body = await reader.ReadToEndAsync();
    }

    if (string.IsNullOrEmpty(body))
    {
        return BadRequest("Token request missing body");
    }

    var parameters = HttpUtility.ParseQueryString(body);
    string authorizationCode = parameters["code"];
    string grantType = parameters["grant_type"];
    string clientId = parameters["client_id"];
    string clientSecret = parameters["client_secret"];
    string redirectUri= parameters["redirect_uri"];

    // Validate any of these parameters here, or call out to an external identity provider with them

    if (_tokens.TryRemove(authorizationCode, out string token))
    {
        return Ok(new TokenResponse()
        {
            AccessToken = token,
            ExpiresIn = 3600,
            TokenType = "custom",
        });
    }
    else
    {
        return BadRequest("Token request body did not contain parameter 'code'");
    }
}

Ara Sunucu Bağlantı Ayarı Yapılandırması

OAuth2 Proxy Hizmetinizi çalıştırdıktan sonra, Azure AI Bot Hizmeti kaynağınızda bir OAuth Hizmet Sağlayıcısı Bağlantı Ayarı oluşturabilirsiniz. Aşağıda açıklanan adımları izleyin.

  1. Bağlantı ayarına bir ad verin.
  2. Genel Oauth 2 hizmet sağlayıcısını seçin.
  3. Bağlantı için bir İstemci kimliği ve İstemci gizli anahtarı girin. Bu değerler gelişmiş veya özel kimlik sağlayıcınız tarafından sağlanabilir veya kullandığınız kimlik sağlayıcısı istemci kimliği ve gizli dizi kullanmıyorsa yalnızca proxy'nize özgü olabilir.
  4. Yetkilendirme URL'si için yetkilendirme REST API'nizin adresini kopyalamanız gerekir, örneğinhttps://proxy.com/api/oauth/authorize.
  5. Belirteç ve Yenileme URL'si için, örneğin belirtecinizin REST API https://proxy.com/api/oauth/tokenadresini kopyalamanız gerekir. Belirteç Değişimi URL'si yalnızca AAD tabanlı sağlayıcılar için geçerlidir ve bu nedenle yoksayılabilir.
  6. Son olarak, uygun kapsamları ekleyin.

ASP.NET web uygulaması için OAuthController

using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading.Tasks;
using System.Web;

namespace CustomOAuthProvider.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class OAuthController : ControllerBase
    {
        ConcurrentDictionary<string, string> _tokens;

        public OAuthController(ConcurrentDictionary<string, string> tokens)
        {
            _tokens = tokens;
        }

        [HttpGet("authorize")]
        public ActionResult Authorize(
            string response_type, 
            string client_id, 
            string state, 
            string redirect_uri, 
            string scope = null)
        {
            if (string.IsNullOrEmpty(state))
            {
                return BadRequest("Authorize request missing parameter 'state'");
            }

            if (string.IsNullOrEmpty(redirect_uri))
            {
                return BadRequest("Authorize request missing parameter 'redirect_uri'");
            }

            // reidrect to an external identity provider, 
            // or for this sample, generte a code and token pair and redirect to the redirect_uri

            var code = Guid.NewGuid().ToString("n");
            var token = Guid.NewGuid().ToString("n");
            _tokens.AddOrUpdate(code, token, (c, t) => token);

            return Redirect($"{redirect_uri}?code={code}&state={state}");
        }

        [HttpPost("token")]
        public async Task<ActionResult> Token()
        {
            string body;

            using (var reader = new StreamReader(Request.Body))
            {
                body = await reader.ReadToEndAsync();
            }

            if (string.IsNullOrEmpty(body))
            {
                return BadRequest("Token request missing body");
            }

            var parameters = HttpUtility.ParseQueryString(body);
            string authorizationCode = parameters["code"];
            string grantType = parameters["grant_type"];
            string clientId = parameters["client_id"];
            string clientSecret = parameters["client_secret"];
            string redirectUri= parameters["redirect_uri"];

            // Validate any of these parameters here, or call out to an external identity provider with them

            if (_tokens.TryRemove(authorizationCode, out string token))
            {
                return Ok(new TokenResponse()
                {
                    AccessToken = token,
                    ExpiresIn = 3600,
                    TokenType = "custom",
                });
            }
            else
            {
                return BadRequest("Token request body did not contain parameter 'code'");
            }
        }
    }

    public class TokenResponse
    {
        [JsonProperty("access_token")]
        public string AccessToken { get; set; }

        [JsonProperty("id_token")]
        public string IdToken { get; set; }

        [JsonProperty("token_type")]
        public string TokenType { get; set; }

        [JsonProperty("expires_in")]
        public int ExpiresIn { get; set; }

        [JsonProperty("refresh_token")]
        public string RefreshToken { get; set; }

        [JsonProperty("scope")]
        public string Scope { get; set; }
    }
}