Skip to content

Instantly share code, notes, and snippets.

@johnfelipe
Created February 18, 2025 16:48
Show Gist options
  • Save johnfelipe/40d769dcb95ff358e3b5fdc63c400c38 to your computer and use it in GitHub Desktop.
Save johnfelipe/40d769dcb95ff358e3b5fdc63c400c38 to your computer and use it in GitHub Desktop.
slug Título
autenticación-y-autorización
Autenticación y Autorización

Integrado en ServiceStack hay un modelo de autenticación simple y extensible que implementa la autenticación de sesión HTTP estándar donde Las cookies de sesión se utilizan para enviar solicitudes autenticadas que hacen referencia a los usuarios de sesión de usuario personalizados POCO en el archivo Proveedor de almacenamiento en caché registrado.

ServiceStack también incluye una serie de proveedores de autenticación que "autentican por solicitud", en este caso la sesión de usuario autenticada solo se conecta y dura durante la vida útil de la corriente IRequest. Los detalles de implementación de cada proveedor de autenticación son los siguientes: transparente para su Aplicación donde se utilizan los mismos Atributos y API para recuperar, validar, autenticar y autorizar a los Usuarios.

El soporte de autenticación de ServiceStack está encapsulado en el complemento opcional, AuthFeature lo que proporciona una manera fácil de declarar registre y configure varios proveedores de autenticación que desee permitir en su aplicación. Es altamente configurable con una serie de características adicionales, como si se habilita el registro integrado para registrar nuevos usuarios, así como los servicios de asignación / anulación de asignación de roles que los administradores pueden usar para asignar roles/permisos a los usuarios existentes.

Creación de un proyecto con ServiceStack Auth

Altamente personalizable y versátil

La autenticación de ServiceStack también es altamente personalizable y versátil, ya que puede elegir entre la gran cantidad de proveedores de autenticación disponibles o heredando de ellos para crear su propio proveedor de autenticación personalizado, heredando AuthUserSession para usar su propio POCO personalizado con información adicional que desea mantener para sus Usuarios, almacenando Sesiones de Usuario en cualquiera de los Proveedores de Almacenamiento en Caché disponibles, agregar lógica personalizada mediante el control de cualquiera de los eventos de autenticación y sesión generados a lo largo del ciclo de vida de autenticación, para especificar en qué repositorio de autenticación de back-end desea conservar sus usuarios autenticados, lo que admite los RDBMS más populares y almacenes de datos NoSQL populares, como se ve en la descripción general de alto nivel a continuación:

Descripción general de alto nivel

Descripción general de la autenticación

Es AuthenticateService el servicio principal que administra la autenticación que delega en el proveedor de autenticación especificado que: realiza la autenticación, disponible a través de sus siguientes puntos de conexión:

  • /auth/{provider} - Autenticarse en un proveedor de autenticación específico
  • /auth - API para comprobar si una solicitud está autenticada: devuelve 200 con información básica de la sesión si está autenticada o 401 si no.
  • /auth/logout - Elimina la sesión autenticada de la caché registrada y borra las cookies de sesión.

Proveedores de autenticación de credenciales

Si desea que ServiceStack administre la autenticación completa de sus aplicaciones y la persistencia de los usuarios, debe utilizar uno de los repositorios de autenticación disponibles y autenticarse en uno de los siguientes proveedores de autenticación:

Proveedor Nombre de la clase Ruta Descripción
Credenciales CredentialsAuthProvider /autenticación/credenciales Autenticación estándar mediante nombre de usuario/contraseña
Autenticación básica BasicAuthProvider Autenticación básica HTTP Nombre de usuario/contraseña enviado a través de HTTP Basic Auth
Autenticación de resumen DigestAuthProvider Autenticación de resumen HTTP Hash de nombre de usuario/contraseña a través de HTTP Digest Auth

Se pueden crear nuevos usuarios a través del /register servicio de registro que se habilita con:

Plugins.Add(new RegistrationFeature());

Proveedores de OAuth

Los siguientes proveedores de OAuth están integrados en ServiceStack y se pueden usar en aplicaciones ASP.NET Core y .NET Framework:

Proveedor Nombre de la clase Ruta Crear enlace a la aplicación OAuth
Facebook (en inglés) FacebookAuthProvider /autenticación/facebook developers.facebook.com/apps
Twitter TwitterAuthProvider /autenticación/twitter dev.twitter.com/apps
Google (en inglés) GoogleAuthProvider /autenticación/google console.developers.google.com
GitHub (en inglés) GithubAuthProvider /auth/github github.com/settings/applications/new
Microsoft MicrosoftGraphAuthProvider /auth/microsoftgraph apps.dev.microsoft.com
LinkedIn (en inglés) LinkedInAuthProvider /autenticación/linkedin www.linkedin.com/secure/developer
Yammer YammerAuthProvider /auth/yammer www.yammer.com/client_applications
Yandex YandexAuthProvider /auth/yandex oauth.yandex.ru/client/new
VK VkAuthProvider /autenticación/vkcom vk.com/editapp?act=create
Odnoklassniki OdnoklassnikiAuthProvider /auth/odnoklassniki www.odnoklassniki.ru/devaccess

Descripción general de la autenticación de sesión

En el siguiente diagrama se describe con más detalle cómo funciona la autenticación estándar basada en sesión y cómo interactúan los diferentes proveedores:

Autenticación basada en sesión

Donde el proveedor de autenticación es único para cada proveedor de autenticación, pero adopta el mismo proceso de autenticación que resulta en el mismo resultado final en el que se conserva un autenticado AuthUserSession en el registrado ICacheClient contra la ss-pid cookie permanente si la Authenticate solicitud RememberMe=true de lo contrario contra ss-id la cookie de sesión temporal, si no.

Después de autenticar una solicitud, sus cookies de sesión se envían en solicitudes posteriores y se validan mediante la función integrada [Authenticate] y Otros [Require*] atributos para restringir el acceso a usuarios válidos:

Solicitudes de sesión

Una vez autenticado, se puede acceder a la sesión de usuarios en sus Servicios utilizando las API con tipo y mínimas IAuthSession :

AuthUserSession session = base.SessionAs<AuthUserSession>();
IAuthSession session = base.GetSession();

De si se ha registrado para usar un POCO UserSession personalizado en el AuthFeature constructor, úselo en lugar de AuthUserSession.

Las sesiones de usuario con tipo también son accesibles en todos los filtros y controladores que tienen acceso a la actual IRequest con:

AuthUserSession session = req.SessionAs<AuthUserSession>();
IAuthSession session = req.GetSession();

Consulta los documentos de la sesión para obtener más información sobre la personalización de las sesiones y el control de diferentes eventos de sesión y autenticación.

Autenticación por proveedores de autenticación de solicitud

Estos proveedores de autenticación incluyen autenticación con cada solicitud, por lo que la sesión de usuario autenticada solo se rellena en el HTTP IRequest y no se guarda en el cliente de caché registrado. A diferencia de los proveedores de autenticación tradicionales anteriores, donde hay una solicitud de "Autenticación" separada para establecer la autenticación, Los proveedores de autenticación que implementan IAuthWithRequest en su lugar envían su autenticación "por solicitud" donde solo se rellena en el : IRequest

Autenticación con proveedores de autenticación de solicitud

Si bien el proceso de autenticación es diferente, continuaría usando las mismas API y atributos para acceder y validar la sesión de usuarios.

Los siguientes proveedores de autenticación IAuthWithRequest implementan y autentican por solicitud:

Proveedor Nombre de la clase Método de autenticación Descripción
JWT JwtAuthProvider Ficha al portador Proveedor de autenticación sin estado mediante tokens web JSON
Claves de API ApiKeyAuthProvider Ficha al portador Permitir el acceso de terceros para autenticarse sin contraseña
Autenticación básica BasicAuthProvider Autenticación básica Autenticación mediante autenticación básica HTTP
Autenticación de resumen DigestAuthProvider Autenticación de resumen Autenticación mediante HTTP Digest Auth

Algunos otros proveedores de autenticación especiales que se autentican por solicitud incluyen:

  • Autenticación de Windows en AspNetWindowsAuthProvider : autenticación mediante autenticación de Windows integrada en ASP.NET.
  • Claims Auth en NetCoreIdentityAuthProvider : pase a través del proveedor de autenticación que delega en ASP.NET Core Identity Auth o Identity Server.

Autenticación ASP.NET Core integrada

Se NetCoreIdentityAuthProvider trata de un adaptador de autenticación bidireccional que permite a ServiceStack utilizar la misma autenticación que el el resto de la aplicación ASP.NET Core y MVC donde habilita los siguientes escenarios populares:

Proveedores de autenticación comunitaria

Configuración básica

Una configuración mínima necesaria para poner en marcha la autenticación básica es la siguiente ( AppHost.Config() derivada de la prueba unitaria AuthTests):

public override void Configure(Container container)
{
    Plugins.Add(new AuthFeature(() => new AuthUserSession(),
        new IAuthProvider[] { 
            new BasicAuthProvider(),       //Sign-in with HTTP Basic Auth
            new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
        }));

    container.Register<ICacheClient>(new MemoryCacheClient());

    var userRepo = new InMemoryAuthRepository();
    container.Register<IAuthRepository>(userRepo);
    
    //The IAuthRepository is used to store the user credentials etc.
    //Implement this interface to adjust it to your app's data storage
}

AuthWebTests es un proyecto sencillo que muestra todos los proveedores de autenticación configurados y funcionando en la misma aplicación. Consulte AppHost para obtener un ejemplo del código y Web.config para obtener un ejemplo de la configuración necesaria para habilitar cada proveedor de autenticación.

Configuración de OAuth

Una vez que tenga el ConsumerKey y ConsumerSecret necesita configurarlo con su host ServiceStack, a través de Web.config, por ejemplo:

<add key="oauth.RedirectUrl"            value="https://yourhostname.com"/>
<add key="oauth.CallbackUrl"            value="https://yourhostname.com/auth/{0}"/>    
<add key="oauth.twitter.ConsumerKey"    value="3H1FHjGbA1N0n0aT5yApA"/>
<add key="oauth.twitter.ConsumerSecret" value="MLrZ0ujK6DwyjlRk2YLp6HwSdoBjtuqwXeHDQLv0Q"/>

Para .NET Core o ASP.NET Core Apps , puede agregar las mismas claves a su appsettings.json, por ejemplo:

{
    "oauth.RedirectUrl":            "https://yourhostname.com",
    "oauth.CallbackUrl":            "https://yourhostname.com/auth/{0}",
    "oauth.twitter.ConsumerKey":    "3H1FHjGbA1N0n0aT5yApA",
    "oauth.twitter.ConsumerSecret": "MLrZ0ujK6DwyjlRk2YLp6HwSdoBjtuqwXeHDQLv0Q",
}

Cada opción de OAuth Config retrocede a la configuración sin el nombre del proveedor. Si es necesario, proporcione una configuración específica de OAuth incluyendo el nombre del proveedor de autenticación en la configuración, por ejemplo:

<add key="oauth.twitter.RedirectUrl"    value="https://yourhostname.com"/>
<add key="oauth.twitter.CallbackUrl"    value="https://yourhostname.com/auth/twitter"/>    

La configuración también se puede especificar en el código al registrar el proveedor de autenticación en el AuthFeature complemento en su AppHost, por ejemplo:

Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] {
    new TwitterAuthProvider(appSettings) { 
        RedirectUrl = "http://yourhostname.com/",
        CallbackUrl = "http://yourhostname.com/auth/twitter",
        ConsumerKey = "3H1FHjGbA1N0n0aT5yApA",
        ConsumerSecret = "MLrZ0ujK6DwyjlRk2YLp6HwSdoBjtuqwXeHDQLv0Q",
    },
}));

:::información La URL de devolución de llamada de cada aplicación debe coincidir con la CallbackUrl de la aplicación, que suele ser: http://yourhostname.com/auth/{Provider}, por ejemplo, http://yourhostname.com/auth/twitter para Twitter. :::

Permitir redireccionamientos externos

Las redirecciones externas utilizadas en los ?continue parámetros de /auth las solicitudes están deshabilitadas de forma predeterminada, se pueden volver a habilitar con:

new AuthFeature(...) {
    ValidateRedirectLinks = AuthFeature.AllowAllRedirects 
}

Repositorio de autenticación

ServiceStack admite la gestión de usuarios en varios almacenes de datos a través de su repositorio de autenticación, abstracción y proveedores integrados.

Persistencia de la sesión

Una vez autenticado, el ** modelo AuthUserSession** se rellena y almacena en la caché mediante uno de los proveedores de almacenamiento en caché compatibles con ServiceStack. Las sesiones de ServiceStack simplemente usan el método ICacheClient API para que cualquier nuevo proveedor agregado se pueda usar tanto para la sesión como para el almacenamiento en caché, que actualmente incluye:

La función de autenticación también le permite especificar su propio tipo personalizado IUserAuthSession donde puede capturar metadatos adicionales con la sesión de sus usuarios que también se conservarán e hidratarán desde la caché, por ejemplo:

Plugins.Add(new AuthFeature(() => new CustomUserSession(), 
    ...
));

:::información Si está utilizando sesiones personalizadas y tiene JsConfig.ExcludeTypeInfo=true, debe habilitarlo explícitamente con JsConfig<TCustomSession>.IncludeTypeInfo=true. :::

Después de la autenticación, el cliente recibirá una cookie con un ID de sesión, que se utiliza para obtener la sesión correcta internamente ICacheClient por ServiceStack. Por lo tanto, puede acceder a la sesión actual en un servicio:

public class SecuredService : Service
{
    public object Get(Secured request)
    {
        var session = this.SessionAs<AuthUserSession>();
        return new SecuredResponse() { Test = "You're" + session.FirstName };
    }
}

Los proveedores de autenticación, almacenamiento en caché y sesión de ServiceStack son API comprobables completamente nuevas, limpias y sin dependencias que no dependen de ASP y carecen de él. Los modelos existentes de membresía, almacenamiento en caché o proveedor de sesiones de NET.

Sesión de administración de AuthSecret

Las solicitudes de superusuario mediante Config.AdminAuthSecret devuelven una UserSession de administrador autenticada cuyos valores por defecto se pueden modificar en AuthFeature.AuthSecretSession:

  • DisplayName:Admin
  • UserName: authsecret
  • AuthProvider: authsecret
  • Roles:Admin
  • UserAuthId: 0

Página de inicio de sesión integrada

AuthFeature Agrega una página /login.html de reserva si el HtmlRedirect permanece sin cambios y no /login.html existe, de lo contrario. si se usa una /login página personalizada en Razor o Script Pages, se seguirán usando en su lugar.

La página predeterminada /login.html proporciona una página de inicio de sesión automático que admite la autenticación a través de credenciales, así como la generación de una dinámica La lista de proveedores de OAuth, por ejemplo, la página NorthwindCrud /login con OAuth de Facebook se ve así:

Si usa una aplicación SPA con enrutamiento del lado del cliente para implementar /login, la página de inicio de sesión predeterminada se puede deshabilitar con:

new AuthFeature {
    IncludeDefaultLogin = false
}

La página de inicio de sesión admite los mismos continue parámetros o ReturnUrl redireccionamientos que la API de cierre de sesión.

Validación mundial

Consulte los documentos de validación mundial anotados para obtener un recorrido detallado y mostrar la implementación de cómo los enfoques **de representación HTML de servidor ** más populares y las tecnologías de representación de la interfaz de usuario del cliente utilizan la misma Autenticación, Registro y Servicios protegidos.

Plantillas de proyectos

La mayoría de las plantillas de proyecto de ServiceStack están configuradas con autenticación lista para usar o se pueden agregar fácilmente a una web vacía Plantilla de proyecto:

:::Sh x nueva web ProjectName :::

Al mezclar las características de autenticación deseadas, por ejemplo, para configurar su aplicación para habilitar la autenticación y el mantenimiento en SQL Server, ejecute:

:::Sh x mix auth auth-db sqlserver :::

Echa un vistazo a la demo de YouTube de Bookings CRUD para obtener una vista previa rápida de esto en acción.

Demostraciones en vivo

Para ilustrar la integración de la autenticación con ServiceStack, consulte la autenticación habilitada Demostraciones en vivo a continuación:

.NET Core

Móvil

.NET Framework

Autenticación y autorización personalizadas

Un buen punto de partida para crear su propio proveedor de autenticación que se basa en la validación de nombre de usuario y contraseña es crear una subclase CredentialsAuthProvider e invalidar el bool TryAuthenticate(service, username, password) método en el que puede proporcionar su implementación personalizada. Si, en cambio, desea autenticarse a través de la autenticación básica HTTP en BasicAuthProvider su lugar, haría una subclase.

Tanto el valor predeterminado de BasicAuthProvider como el CredentialsAuthProvider (que extiende) se pueden ampliar y su comportamiento se puede sobrescribir. A continuación se muestra un ejemplo:

Async AuthProvider personalizado

using ServiceStack;
using ServiceStack.Auth;

// From v5.10+
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
    public override async Task<bool> TryAuthenticateAsync(IServiceBase authService, 
        string userName, string password, CancellationToken token=default)
    {
        //Add here your custom auth logic (database calls etc)
        //Return true if credentials are valid, otherwise false
    }

    public override async Task<IHttpResult> OnAuthenticatedAsync(IServiceBase authService, 
        IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo, 
        CancellationToken token=default)
    {
        //Fill IAuthSession with data you want to retrieve in the app eg:
        session.FirstName = "some_firstname_from_db";
        //...

        //Call base method to Save Session and fire Auth/Session callbacks:
        return await base.OnAuthenticatedAsync(authService, session, tokens, authInfo, token);

        //Alternatively avoid built-in behavior and explicitly save session with
        //session.IsAuthenticated = true;
        //await authService.SaveSessionAsync(session, SessionExpiry, token);
        //authService.Request.Items[Keywords.DidAuthenticate] = true;
        //return null;
    }
}

Sincronizar AuthProvider personalizado

using ServiceStack;
using ServiceStack.Auth;

public class CustomCredentialsAuthProvider : CredentialsAuthProviderSync
{
    public override bool TryAuthenticate(IServiceBase authService, 
        string userName, string password)
    {
        //Add here your custom auth logic (database calls etc)
        //Return true if credentials are valid, otherwise false
    }

    public override IHttpResult OnAuthenticated(IServiceBase authService, 
        IAuthSession session, IAuthTokens tokens, 
        Dictionary<string, string> authInfo)
    {
        //Fill IAuthSession with data you want to retrieve in the app eg:
        session.FirstName = "some_firstname_from_db";
        //...

        //Call base method to Save Session and fire Auth/Session callbacks:
        return base.OnAuthenticated(authService, session, tokens, authInfo);

        //Alternatively avoid built-in behavior and explicitly save session with
        //session.IsAuthenticated = true;
        //authService.SaveSession(session, SessionExpiry);
        //authService.Request.Items[Keywords.DidAuthenticate] = true;
        //return null;
    }
}

A continuación, debe registrar su proveedor de autenticación de credenciales personalizadas:

//Register all Authentication methods you want to enable for this web app.
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
    new IAuthProvider[] {
        new CustomCredentialsAuthProvider(), //HTML Form post of User/Pass
    }
));

De forma predeterminada, el complemento AuthFeature registra automáticamente las siguientes rutas de servicio (reemplazables):

new AuthFeature = {
  ServiceRoutes = new Dictionary<Type, string[]> {
    { typeof(AuthenticateService),  new[]{ "/auth", "/auth/{provider}" }},
    { typeof(AssignRolesService),   new[]{ "/assignroles" }},
    { typeof(UnAssignRolesService), new[]{ "/unassignroles" }},
  }
};

Cerrar sesión

Puede realizar un GET o POST para /auth/logout cerrar la sesión del usuario autenticado o, si usa el cliente de C#, puede cerrar la sesión con:

client.Post(new Authenticate { provider = "logout" });

URL de redireccionamiento

Al cerrar la sesión, se eliminará la sesión del usuario del servidor y las cookies de sesión del cliente y se redirigirá a la URL en continueo el parámetro ReturnUrlQueryStringAuthFeature.HtmlRedirectReturnParam o **FormData Request ** configurado ** ** . Si no se especifica ninguna redirección, recurrirá a la redirección a session.ReferrerUrl, Referer encabezado HTTP o configurado AuthProvider.CallbackUrl.

Autenticación con clientes de servicio .NET

En el cliente, puede usar los clientes de servicio de C#/.NET para consumir fácilmente los servicios autenticados.

Para autenticarse usando su CustomCredentialsAuthProvider mediante POST una Authenticate solicitud, por ejemplo:

var client = new JsonServiceClient(BaseUrl);

var authResponse = client.Post(new Authenticate {
    provider = CredentialsAuthProvider.Name, //= credentials
    UserName = "[email protected]",
    Password = "p@55w0rd",
    RememberMe = true,
});

Si la autenticación se ha realizado correctamente, la instancia del cliente de servicio client se rellenará con cookies de sesión autenticadas, lo que permitirá llamar a servicios autenticados, por ejemplo:

var response = client.Get(new GetActiveUserId());

Si también se ha registradoBasicAuthProvider, permitirá que sus servicios acepten la autenticación básica HTTP, que está integrada en los clientes de servicio con los que puede rellenar en el cliente de servicio:

client.UserName = "[email protected]";
client.Password = "p@55w0rd";

Lo que también le permitirá acceder a Servicios protegidos, por ejemplo:

var response = client.Get(new GetActiveUserId());

Aunque detrás de escena termina haciendo 2 solicitudes, la 1ª solicitud envía una solicitud normal que será rechazada con un 401 Unauthorized y si el servidor indica que tiene el BasicAuthProvider habilitado volverá a enviar la solicitud con las credenciales de autenticación básica HTTP.

En su lugar, puede guardar la latencia de la solicitud de desafío de autenticación adicional especificando que el cliente siempre debe enviar la autenticación básica con cada solicitud:

client.AlwaysSendBasicAuthHeader = true;

Autenticación con HTTP

Para autenticarse con su CustomCredentialsAuthProvider (que hereda de CredentialsAuthProvider) debe PUBLICAR:

POST localhost:60339/auth/credentials?format=json

{
    "UserName": "admin",
    "Password": "test",
    "RememberMe": true
}

Cuando el cliente intenta autenticarse con la solicitud anterior y la autenticación se ha realizado correctamente, el cliente recuperará algunas cookies con un identificador de sesión que identifican al cliente en cada llamada al servicio web.

Autenticación a través de OAuth AccessTokens

Para mejorar la integración de OAuth Sign In desde aplicaciones móviles o de escritorio nativas, también puede autenticarse a través de AccessTokens, lo que puede simplificar drásticamente el desarrollo y la experiencia del usuario al poder aprovechar los SDK nativos de Facebook, Twitter y Google Client para iniciar sesión localmente y luego reutilizar su **AccessToken local ** para autenticarse con servidores ServiceStack back-end.

Un ejemplo de uso de esta función es en los inicios de sesión integrados de Facebook, Twitter y Google en Java Chat de Android, que también puede iniciar sesión automáticamente los usuarios con AccessTokens guardados.

Esta capacidad está disponible en los proveedores de OAuth más populares a continuación:

  • FacebookAuthProvider - Iniciar sesión con Facebook
  • TwitterAuthProvider - Iniciar sesión con Twitter
  • GithubAuthProvider - Iniciar sesión con Github
  • GoogleOAuth2Provider - Iniciar sesión con Google

También se puede habilitar en otros proveedores de OAuth2 mediante la implementación VerifyAccessToken manual validar si el AccessToken proporcionado es válido con la aplicación OAuth registrada. La API para validar el acceso Los tokens no forman parte de la especificación de OAuth2 y son diferentes (y a menudo faltan) para otros proveedores de OAuth2.

Por ejemplo, utiliza GoogleOAuth2Provider una VerifyAccessToken implementación similar a:

new GoogleOAuth2Provider {
    VerifyAccessToken = accessToken => {
        var url = $"https://www.googleapis.com/oauth2/v1/tokeninfo?access_token={accessToken}";
        var json = url.GetJsonFromUrl();
        var obj = JsonObject.Parse(json);
        return obj["issued_to"] == ConsumerKey;
    }
}

Autenticación de cliente con AccessToken

Los clientes pueden utilizar esta característica con las nuevas AccessToken propiedades y AccessTokenSecret en las propiedades existentes Authenticate Solicitud de DTO, enviada con el proveedor para el que es el AccessToken, por ejemplo:

var response = client.Post(new Authenticate {
    provider = "facebook",
    AccessToken = facebookAccessToken,
    RememberMe = true,
});

:::información La mayoría de los proveedores de OAuth solo requieren el envío de un AccessToken con Twitter como la excepción, que también requiere el envío de un AccessTokenSecret :::

Caché de sesiones de usuario

ServiceStack utiliza el proveedor de caché que se registró en el contenedor de IoC:

//Register to use an In Memory Cache Provider (default)
container.Register<ICacheClient>(new MemoryCacheClient());

//Configure an alt. distributed persisted cache, E.g Redis:
//container.Register<IRedisClientsManager>(c => 
//    new RedisManagerPool("localhost:6379"));

::: info Consejo Si tiene varios servidores que ejecutan el mismo servicio ServiceStack, puede usar Redis para compartir las sesiones entre estos servidores :::

Por favor, mire SocialBootstrapApi para obtener un ejemplo completo.

:::información Por supuesto, también puede implementar su propio mecanismo de autenticación personalizado. No está obligado a usar el mecanismo de autenticación ServiceStack integrado :::

Atributos de validación declarativa

La forma recomendada de proteger las API es usar los atributos de validación declarativa que, a medida que están desacoplados de cualquier implementación, se pueden anotar de forma segura en las DTO de solicitud sin agregar ninguna dependencia de implementación. Además, al anotar los atributos de autorización y validación en los DTO de solicitud, captura esta información en las DTO reutilizables de las API, filtrando esta información a los clientes donde pueden proporcionar experiencias de usuario enriquecidas.

Atributos de autorización

Los atributos de autorización con tipo disponibles incluyen:

Atributo Descripción
[ValidateIsAuthenticated] Proteger el acceso a esta API solo a los usuarios autenticados
[ValidateIsAdmin] Proteger el acceso a esta API solo a los usuarios administradores
[ValidateHasPermission] Proteja el acceso a esta API solo a los usuarios asignados con TODOS los permisos
[ValidateHasRole] Proteja el acceso a esta API solo a los usuarios asignados con TODOS los roles

Dónde se pueden anotar en Solicitar DTO para proteger las API:

[ValidateIsAuthenticated]            // or [ValidateRequest("IsAuthenticated")]
[ValidateIsAdmin]                    // or [ValidateRequest("IsAdmin")]
[ValidateHasRole(role)]              // or [ValidateRequest($"HasRole(`{role}`)")]
[ValidateHasPermission(permission)]  // or [ValidateRequest($"HasPermission(`{permission}`)")
public class Secured {}

El atributo Authenticate

El [Authenticate] atributo de filtro de solicitud le dice a ServiceStack qué servicios necesitan autenticación agregándolo a sus implementaciones de servicio, por ejemplo:

[Authenticate]
public class SecuredService : Service
{
    public object Get(Secured request)
    {
        IAuthSession session = this.GetSession();
        return new SecuredResponse() { Test = "You're" + session.FirstName };
    }

    public object Put(Secured request)
    {
        return new SecuredResponse() { Test = "Valid!" };
    }

    public object Post(Secured request)
    {
        return new SecuredResponse() { Test = "Valid!" };
    }

    public object Delete(Secured request)
    {
        return new SecuredResponse() { Test = "Valid!" };
    }
}

Si lo desea, esa autenticación solo es necesaria para las solicitudes GET y PUT, por ejemplo, debe proporcionar algunos parámetros adicionales al Authenticate atributo.

[Authenticate(ApplyTo.Get | ApplyTo.Put)] 

Atributos RequiredRole y RequiredPermission

ServiceStack también incluye un rol integrado y atributos de autorización basados en permisos donde puede aplicar los atributos de filtro de [Required*] solicitud en sus clases de servicio para aplicarlos a todos los servicios o limitarlos a un solo servicio:

[Authenticate]
//All HTTP (GET, POST...) methods need "CanAccess"
[RequiredRole("Admin")]
[RequiredPermission("CanAccess")]
public class MyServices : Service
{
    public object Get(Secured request) {}

    [RequiredPermission("CanAdd")]
    public object Put(Secured request) {}
    
    [RequiredPermission("CanAdd")]
    public object Post(Secured request) {}
    
    [RequiredPermission("AdminRights", "CanDelete")]
    public object Delete(Secured request) {}
}

Ahora el cliente necesita los permisos:

  • CanAccess para realizar una solicitud GET
  • CanAccess, CanAdd para realizar una solicitud PUT/POST
  • CanAccess, AdminRights y CanDelete para realizar una solicitud DELETE

Si, en cambio, desea permitir el acceso a los usuarios en CUALQUIER rol o uso de permisos:

[RequiresAnyRole("Admin","Member")]
[RequiresAnyRole(ApplyTo.Put | ApplyTo.Post, "Admin","Owner","Member")]
[RequiresAnyPermission(ApplyTo.Delete, "AdminRights", "CanDelete")]
public class MyServices : Service
{
    public object Get(Secured request) {}
    public object Put(Secured request) {}
    public object Post(Secured request) {}
    public object Delete(Secured request) {}
}

Estos atributos también se pueden aplicar a las DTO de solicitud, sin embargo, como agregarían una dependencia a ServiceStack.dll, se recomienda

Habilitación de la autenticación en diferentes niveles

Uso del [Autentificar] atributo

Puede proteger los servicios agregando el [Authenticate] atributo en la Acción:

class MyService : Service 
{
    [Authenticate] 
    public object Get(Protected request) { ... }
}

La solicitud DTO

[Authenticate] 
class Protected { ... }

O la implementación del servicio

[Authenticate] 
class MyService : Service 
{
    public object Get(Protected request) { ... }
}

O bien, heredando de una clase base

[Authenticate] 
class MyServiceBase : Service { ... }

class MyService : MyServiceBase {
    public object Get(Protected request) { ... }
}

Uso de un filtro de solicitud global

De lo contrario, puede usar un filtro de solicitudes global si desea restringir todas las solicitudes de otra manera, por ejemplo, algo como:

GlobalRequestFiltersAsync.Add(async (req, res, requestDto) =>
{
    if (ShouldProtectRequest(requestDto)) 
    {
        await new AuthenticateAttribute().ExecuteAsync(req, res, requestDto);
    }
});

Personalización de AuthProviders

CustomValidationFilter

El CustomValidationFilter on all AuthProviders le permite agregar lógica de verificación posterior después de que un usuario haya iniciado sesión con un proveedor de OAuth y se recuperen sus metadatos de OAuth. El filtro le permite devolver un IHttpResult para controlar qué respuesta de error se devuelve, por ejemplo:

new FacebookAuthProvider(appSettings) { 
    CustomValidationFilter = authCtx => CustomIsValid(authCtx) 
        ? authCtx.Service.Redirect(authCtx.Session.ReferrerUrl
            .AddHashParam("f","CustomErrorCode"))
        : null,
}

O podría usarse para redirigir una red o usuarios a una página "No disponible en su área" con:

Plugins.Add(new AuthFeature(..., 
    new IAuthProvider[] {
        new CredentialsAuthProvider {
            CustomValidationFilter = authCtx => 
                authCtx.Request.UserHostAddress.StartsWith("175.45.17")
                    ? HttpResult.Redirect("http://host.com/are-not-available")
                    : null
        }   
    }));

Validación de nombre de usuario

La validación de nombre de usuario para todos los repositorios de autenticación se puede configurar en:

Plugins.Add(new AuthFeature(...){
    ValidUserNameRegEx = new Regex(@"^(?=.{3,20}$)([A-Za-z0-9][._-]?)*$", RegexOptions.Compiled),
})

En lugar de RegEx, puede optar por validar mediante un predicado personalizado. En el ejemplo siguiente se garantiza que los nombres de usuario no incluyan caracteres específicos:

Plugins.Add(new AuthFeature(...){
    IsValidUsernameFn = userName => userName.IndexOfAny(new[] { '@', '.', ' ' }) == -1
})

Validador de AccountLocked

Utilícelo AccountLockedValidator para anular la lógica para determinar cuándo una cuenta está bloqueada, por ejemplo, de forma predeterminada, una cuenta está bloqueada cuando tiene un LockedDate pero Se puede cambiar para permitir el bloqueo de cuentas en una fecha futura con:

new CredentialsAuthProvider {
    AccountLockedValidator = (authRepo, userAuth, tokens) => 
        userAuth.LockedDate != null && userAuth.LockedDate <= DateTime.UtcNow;
}

Como alternativa, si usa un proveedor de autenticación personalizado, puede invalidar IsAccountLocked() para invalidar este comportamiento.

Guardar metadatos de OAuth extendidos

La nueva SaveExtendedUserInfo propiedad (habilitada de forma predeterminada) en todos los proveedores de OAuth le permite controlar si desea guardar los metadatos de OAuth extendidos disponibles (en UserAuthDetails.Items) al iniciar sesión a través de OAuth.

MaxLoginAttempts

La MaxLoginAttempts función le permite bloquear una cuenta de usuario después de varios intentos de inicio de sesión no válidos, por ejemplo:

Plugins.Add(new AuthFeature(...) {
    MaxLoginAttempts = 5   // Lock user after 5 Invalid attempts
});

Adición de AuthProviders con complementos

Los plugins pueden registrar AuthProviders llamando antes RegisterAuthProvider() de que se AuthFeature registre el plugin, lo que se puede lograr en los plugins haciendo que implementen IPreInitPlugin:

public class MyPlugin : IPreInitPlugin
{
    public void BeforePluginsLoaded(IAppHost appHost)
    {
        appHost.GetPlugin<AuthFeature>().RegisterAuthProvider(new MyAuthProvider());
    }
}

Filtro de respuesta de autenticación

Los proveedores de autenticación pueden personalizar el AuthenticateResponse valor devuelto implementando IAuthResponseFilter dónde se devolverá la llamada con un AuthFilterContext rellenado para las solicitudes DTO de solicitud de autenticación correctas o AuthResultContext para las solicitudes de OAuth correctas:

public interface IAuthResponseFilter
{
    // Intercept successful Authenticate Request DTO requests
    void Execute(AuthFilterContext authContext);
    
    // Intercept successful OAuth redirect requests
    Task ResultFilterAsync(AuthResultContext authContext, CancellationToken token=default);
}

public class AuthFilterContext
{
    public AuthenticateService AuthService    // Instance of AuthenticateService
    public IAuthProvider AuthProvider         // Selected Auth Provider for Request
    public IAuthSession Session               // Authenticated Users Session
    public Authenticate AuthRequest           // Auth Request DTO
    public AuthenticateResponse AuthResponse  // Auth Response DTO
    public string ReferrerUrl                 // Optimal Session Referrer URL to use redirects
    public bool AlreadyAuthenticated          // If User was already authenticated
    public bool DidAuthenticate               // If User Authenticated in this request
}

public class AuthResultContext
{
    public IHttpResult Result                 // Response returned for this successful Auth Request
    public IServiceBase Service               // Instance of Service used in this Request
    public IRequest Request                   // Current HTTP Request Context
    public IAuthSession Session               // Authenticated Users Session
}

Los filtros se pueden usar para modificar las propiedades de las AuthenticateResponse solicitudes de redireccionamiento correctas de DTO u OAuth. Para reemplazar completamente el AuthenticateResponse valor devuelto, puede especificar un AuthFeature.AuthResponseDecoratorarchivo .

ICustomUserAuth

La ICustomUserAuth interfaz se puede implementar en repositorios de autenticación de usuario que permiten reemplazar el UserAuth y UserAuthDetails tablas devolviendo el tipo concreto que se debe usar en su lugar:

public interface ICustomUserAuth
{
    IUserAuth CreateUserAuth();
    IUserAuthDetails CreateUserAuthDetails();
}

Esto permite usar el mismo RegistrationFeature y RegisterService manejar el registro de nuevos usuarios con los sustituidos IUserAuth y IUserAuthDetails Tipos.

LoadUserAuthFilter

LoadUserAuthFilter activado AspNetWindowsAuthProvider permite recuperar información más detallada sobre los usuarios autenticados de Windows durante la autenticación de autenticación de Windows mediante el archivo . Los servicios de ActiveDirectory de NET, por ejemplo:

//...
new AspNetWindowsAuthProvider(this) {
    LoadUserAuthFilter = LoadUserAuthInfo
}
//...

public void LoadUserAuthInfo(AuthUserSession userSession, 
    IAuthTokens tokens, Dictionary<string, string> authInfo)
{
    if (userSession == null) return;
    using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
    {
        var user = UserPrincipal.FindByIdentity(pc, userSession.UserAuthName);
        tokens.DisplayName = user.DisplayName;
        tokens.Email = user.EmailAddress;
        tokens.FirstName = user.GivenName;
        tokens.LastName = user.Surname;
        tokens.FullName = (String.IsNullOrWhiteSpace(user.MiddleName))
            ? $"{user.GivenName} {user.Surname}"
            : $"{user.GivenName} {user.MiddleName} {user.Surname}";
        tokens.PhoneNumber = user.VoiceTelephoneNumber;
    }
}

PopulateUserRoles personalizables en AspNetWindowsAuthProvider

Utiliza AspNetWindowsAuthProvider la API pública IPrincipal.IsInRole() para determinar si un usuario está en un rol de autenticación de Windows en particular, sin embargo, esto puede ser lento cuando se necesita consultar una gran cantidad de roles en LDAP, ya que tendría que realizar una búsqueda de LDAP para cada rol.

El rendimiento de esto ahora se puede mejorar especificando una implementación personalizada PopulateUserRoles que anule cómo se resuelven los roles de usuario, por ejemplo:

new AspNetWindowsAuthProvider (AppSettings) {
    PopulateUserRoles = (request, user, session) => {
        using (WindowsIdentity userId = request?.LogonUserIdentity)
        {
            List roles = new List();
            if (userId?.Groups != null)
            {
                foreach (var group in userId.Groups)
                {
                    // Remove the domain name from the name of the group, 
                    // if it has it, and you don't need it. 
                    var groupName = new SecurityIdentifier(group.Value)
                        .Translate(typeof(NTAccount)).ToString();
                    if (groupName.Contains("\")) 
                    groupName = groupName.Split('\')[1]; 
                    roles.Add(groupName);
                }
            }
            session.Roles = roles;
        }
    }
}

Solicitudes autenticadas en proceso

Puede habilitar la CredentialsAuthProvider opción para permitir que ** las solicitudes en proceso se autentiquen sin una contraseña con:**

new CredentialsAuthProvider {
    SkipPasswordVerificationForInProcessRequests = true,
}

Cuando está habilitado, permite ** que las solicitudes de servicio en proceso inicien sesión como un usuario especificado sin necesidad de proporcionar su contraseña. **

Por ejemplo, esto podría usarse para crear un servicio de solo administrador restringido ** en la intranet** que le permita iniciar sesión como otro usuario para que pueda depurar su cuenta sin conocer su contraseña con:

[RequiredRole("Admin")]
[Restrict(InternalOnly=true)]
public class ImpersonateUser 
{
    public string UserName { get; set; }
}

public class MyAdminServices : Service
{
    public async Task<object> Any(ImpersonateUser request)
    {
        using var service = base.ResolveService<AuthenticateService>(); //In Process
        return await service.PostAsync(new Authenticate {
            provider = AuthenticateService.CredentialsProvider,
            UserName = request.UserName,
        });
    }
}

:::información Sus servicios pueden usar el nuevo Request.IsInProcessRequest() para identificar los servicios que se ejecutaron en proceso :::

Sesiones de usuario personalizadas mediante tokens JWT

El proveedor de autenticación JWT permite un enfoque más flexible para suplantar a los usuarios, ya que lo permiten Creación manual de tokens JWT para construir una sesión de usuario personalizada con metadatos personalizados, Roles y permisos.

IAuthMetmetProvider

IAuthMetadataProvider proporciona una manera de personalizar authInfo en todos los AuthProviders. También permite anular cómo se devuelven los metadatos de autenticación extendidos, como profileUrl.

public interface IAuthMetadataProvider
{
   void AddMetadata(IAuthTokens tokens, Dictionary<string,string> authInfo);

   string GetProfileUrl(IAuthSession authSession, string defaultUrl = null);
}

:::información Para invalidar con una implementación personalizada, regístrese IAuthMetadataProvider en el IOC :::

Generar nuevas cookies de sesión en la autenticación

AuthFeature también regenera nuevas cookies de sesión cada vez que los usuarios inician sesión, este comportamiento se puede deshabilitar con:

Plugins.Add(new AuthFeature(...) {
    GenerateNewSessionCookiesOnAuthentication = false
});

Alias de configuración de OAuth ClientId y ClientSecret

Los proveedores de OAuth pueden usar ClientId ClientSecret alias and en lugar de ConsumerKey y ConsumerSecret, por ejemplo:

<appSettings>
    <add key="oauth.twitter.ClientId" value="..." />
    <add key="oauth.twitter.ClientSecret" value="..." />
</appSettings>

Encabezado HTTP de autorización de anulación

Los filtros de solicitud pueden anular el encabezado HTTP de autorización utilizado en los proveedores de autenticación con:

httpReq.Items[Keywords.Authorization] = $"Bearer {token}";

Las solicitudes de autenticación GET están deshabilitadas de forma predeterminada

Las solicitudes GET /auth/{provider} están deshabilitadas de forma predeterminada para desalentar el envío de información confidencial en la dirección URL.

Las excepciones actuales que aún permiten ** solicitudes GET** incluyen:

  • /auth - Se utiliza para comprobar si un usuario está autenticado
  • /auth/logout - Cerrar sesión
  • Todos los proveedores de OAuth que inician su flujo de OAuth navegando a /auth/{provider}

Puede permitir **** solicitudes de autenticación GET con:

new AuthFeature {
    AllowGetAuthenticateRequests = req => true
}

Aunque se recomienda cambiar el código para usarlo POST en lugar de GET solicitudes. De lo contrario, puede utilizar el IRequest req parámetro para comprobarlo en una lista blanca de tipos de solicitudes conocidas.

Recursos de la comunidad

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment