#tide #身份提供者 #OpenID

tide-openidconnect

Tide的OpenID Connect中间件

1个不稳定版本

0.1.0 2021年8月12日

#444认证

每月49次下载

MIT/Apache

44KB
456 代码行

tide-openidconnect

Build Status Latest version Documentation License Contributor Covenant

Tide的OpenID Connect中间件。

此crate提供中间件,可用于验证Tide应用程序的用户,可选地阻止未认证的请求访问某些路由。中间件不与用户凭据交互、存储或以其他方式处理用户凭据,而是依赖于OpenID Connect身份提供者进行用户认证。

身份提供者管理用户凭据,可能允许或不允许用户注册,并使用OAuth 2.0框架允许应用程序请求令牌。这些令牌然后可用于识别用户并授予他们对应用程序的访问权限。此crate提供了与身份提供者集成、执行令牌交换并将结果提供给Tide请求所需的功能。

例如,Auth0AzureGoogle是几个兼容OpenID Connect的身份提供者示例。

用法

将其添加到您的Cargo.toml

[dependencies]
tide-openidconnect = "0.1"

示例

use tide_openidconnect::{OpenIdConnectRequestExt, OpenIdConnectRouteExt};

#[async_std::main]
async fn main() -> tide::Result<()> {
    let mut app = tide::new();

    // OpenID Connect middleware *requires* session storage. Note that the
    // cookies must be configured with `SameSite::Lax`.
    app.with(
        tide::sessions::SessionMiddleware::new(
            tide::sessions::MemoryStore::new(),
            b"don't actually use a hardcoded secret",
        )
        .with_same_site_policy(tide::http::cookies::SameSite::Lax),
    );

    // Initialize the OpenID Connect middleware; normally all of these
    // configuration values would come from an environment-specific config
    // file, and in fact that is why they are in their own struct (so that
    // you can deserialize that struct from a file or environment variables).
    app.with(
        tide_openidconnect::OpenIdConnectMiddleware::new(
            &tide_openidconnect::Config {
                issuer_url: tide_openidconnect::IssuerUrl::new("https://your-tenant-name.us.auth0.com/".to_string()).unwrap(),
                client_id: tide_openidconnect::ClientId::new("app-id-goes-here".to_string()),
                client_secret: tide_openidconnect::ClientSecret::new("app-secret-goes-here".to_string()),
                redirect_url: tide_openidconnect::RedirectUrl::new("http://your.cool.site/callback".to_string()).unwrap(),
                idp_logout_url: None,
            }
        )
        .await,
    );

    // Define a basic Tide route, but protect it with the middleware's
    // `.authenticated()` route extension.
    app.at("/").authenticated().get(|req: tide::Request<()>| async move {
        Ok(format!(
            "If you got this far, then the request is authenticated, and your user id is {:?}",
            req.user_id()
        ))
    });

    app.listen("127.0.0.1:8000").await?;
    Ok(())
}

示例目录中查看更多示例。

登录流程

此中间件使用OAuth 2.0 授权码授予流程,这是一种基于重定向的流程:用户导航到登录路径(默认为/login),然后中间件将浏览器重定向到身份提供者的授权端点。登录成功后,浏览器将被重定向到登录着陆页

启动此过程的一种方法是使用is_authenticated()请求扩展检查每个请求的认证状态,然后在请求未认证时显示登录路径的链接。

此包还提供了一个路由扩展,可以将未认证的请求强制导向登录过程。这是一种保护路由而无需逐个检查请求认证状态的方法。使用此路由扩展,未认证的请求将自动将浏览器重定向到登录路径,然后到身份提供者。

请注意,使用此路由扩展存在一些注意事项;有关更多信息,请参阅OpenIdConnectRouteExt文档。

注销流程

用户可以通过导航到注销路径(默认为/logout)来注销应用程序;这将销毁他们的整个Tide会话并将他们返回到注销登录路径。您可以选择性地配置注销过程,只清除会话中的认证状态,保留会话数据的其余部分。

某些身份提供者还支持清除与提供者相关的浏览器状态,您的应用程序可以通过在配置中间件时设置idp_logout_url来可选地启用该功能。

Tide路由拦截

此中间件使用三个路由来执行OAuth 2.0流程的功能。以下是这些路径的默认值,其中两个已在上面描述,所有这些路径都可以更改

  • /login -- 启动OAuth 2.0登录过程。
  • /logout -- 销毁会话状态,并可选择清除身份提供者的状态。
  • /callback -- 身份提供者在成功登录后将浏览器发送到的“重定向URL”。

您不需要在Tide服务器中定义这些路由;中间件拦截对这些路径的GET请求并自行处理。由于这种行为,这些路径在您的应用程序中不可用。

会话中间件要求

OpenID Connect中间件的主要输出是在Tide请求对象中添加有关请求认证状态的信息。Tide的会话中间件用于跟踪此状态,因此OpenID Connect中间件需要您在Tide应用程序中安装和配置会话中间件。如果会话中间件不存在,此中间件将在第一次登录请求时panic。

此外,由于OAuth 2.0流程中的各种HTTP重定向,需要将会话cookie配置为具有SameSite::Lax安全策略。只要您的GET(以及HEADOPTIONSTRACE)请求不更改状态或作为处理请求的一部分执行副作用操作,这就是安全的。保护“安全”(只读)的HTTP方法,而这些方法实际上并不是安全的,是使用默认会话cookie策略SameSite::Strict的主要原因。针对使用cookie的未安全HTTP API的攻击称为跨站请求伪造(CSRF)攻击,而SameSite::Strict是防御这些攻击的最简单方法之一,但只要您的GET(以及HEAD和...)请求仅用于返回数据,则SameSite::Lax是安全的。

请注意,OpenID Connect 中间件在处理 OAuth 2.0 GET 请求时会修改认证状态,但同时也实现了多级 CSRF 防护措施,以保护这些 GET 请求免受恶意攻击。

行为准则

本项目遵循贡献者行为准则。这描述了所有贡献者应遵守的最基本行为规范。

许可

许可方式为以下之一

您可选择其中一种。

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义,您有意提交的任何贡献,都将按上述方式双许可,不附加任何额外的条款或条件。

依赖

~29–42MB
~851K SLoC