使用OAuth2进行身份验证

本教程介绍GeoServer OAuth2支持,并介绍针对OAuth2提供程序设置身份验证的过程。建议 身份验证链 在继续之前请阅读。

OAuth2协议和地理服务器OAuth2核心模块

此模块允许GeoServer根据 OAuth2 Protocol .

为了使模块正常工作,必须同时设置和配置 oauth2oauth2-xxxx-extension (其中xxxx是提供商,例如Google、GitHub、OpenID、geonode)。这两个文件都包含在一个ZIP文件中,该文件从 GeoServer build server (根据需要更改版本)-搜索 sec-oauth2

第一个包含OAuth2核心模块的必要依赖项。此模块包含地理服务器安全筛选器、OAuth2令牌服务的基类和地理服务器GUI面板的实现。

第二个为每个提供者提供OAuth2实现。由于在几乎所有情况下,OAuth2提供程序之间唯一不同的是端点URI和客户端连接信息(不仅是密钥-公共和秘密-还有用户配置文件表示),为了允许Geoserver连接到特定的OAuth2提供程序,只需安装OAuth2核心模块插件(并通过Geoserver图形用户界面正确配置参数-有关详细信息,请参阅下一节)以及OAuth2 REST令牌模板和资源详细信息的具体实现。

目前,这个模块附带了Google OAuth2 Provider的示例扩展。这是一个特殊的情况,因为Google JWT的响应不是标准的,因此我们必须定义并注入 GoogleUserAuthenticationConverter 对一个有效的 access_token 并将其转换为OAuth2标准版本。

除此之外,最有趣的部分是基类的实现 GeoServerOAuth2SecurityConfiguration .

后者包含 OAuth2RestTemplate .

在下一节中,我们将看到如何在对GoogleOAuth2提供者进行身份验证的geoserver上安装和配置OAuth2安全过滤器。

配置Google身份验证提供程序

首先要做的是配置OAuth2提供程序并获取 Client IDClient Secret 钥匙。

  1. 从Google API控制台获取OAuth 2.0凭证。

    参观 Google API Console 以获取OAuth 2.0凭据,如Google和应用程序都知道的客户端ID和客户端机密。值集根据您正在构建的应用程序类型而变化。例如,JavaScript应用程序不需要机密,但web服务器应用程序需要。

    • 使用有效的Google帐户登录

      ../../_images/google_api_console001.png
    • 点击 APIs & Services

      ../../_images/google_api_console002.png
    • 点击 Credentials

      ../../_images/google_api_console003.png

      备注

      第一次登陆时,谷歌会要求至少创建一个项目。

      ../../_images/google_api_console004.png

      在本教程中,我们将创建一个示例项目。您可以通过 Google API Console 后来。

      ../../_images/google_api_console005.png

      如果没有 Credentials 如果存在,将要求您创建新的。

      ../../_images/google_api_console006.png
  2. 选择现有的(或创建新的) OAuth Client ID

    ../../_images/google_api_console007.png
  3. 配置新的 Web application

    • 如果这是您第一次创建 OAuth Client ID ,将要求您创建新的 consent screen

      ../../_images/google_api_console008.png
    • 自定义 consent screen

      警告

      仅当您是第一次定义 Web application 在一个新项目上。如果您没有组织,则只能从下面的屏幕中选择外部类型。

      ../../_images/google_api_console009.png
    • 填写下面的表格并点击 save and continue 直到所有标签都填满为止。
      ../../_images/google_api_console010.png

      备注

      稍后也可以对其进行编辑和更新(请参阅下面这一节的最后一点)

    • 在凭据页面中,单击 CREATE CREDENTIALS > OAuth Client ID 并选择 Application type -> Web application

      警告

      只有在第一次定义 Web application 在一个新项目上。

      ../../_images/google_api_console010a.png
    • 添加 Name 以及 Authorized redirect URIs 如下所示。

      备注

      此示例创建一个处理默认本地URL的客户端 http://localhost:8080/geoserver . 当然,这只适用于本地实例,不能用于生产系统。

      但是,可以添加尽可能多的 Authorized redirect URIs 你需要一个新的 Web application .

      也可以创造许多 Client credentials 定制的 consent screenWeb application ,这取决于您的具体需要。每个公共GeoServer实例(或属于特定项目的GeoServer集群)都应该有自己的特定 Client credentials .

      ../../_images/google_api_console011.png

      备注

      始终为每个URI添加两个条目。一个没有结尾的 / 还有一个。

      ../../_images/google_api_console012.png
  4. 点击 Create 并注意到 Client ID 以及 Client Secret .

    在程序结束时,Google将显示一个小对话框,其中 Client ID 以及 Client Secret . 这些信息总是可以从 Google API Console

    ../../_images/google_api_console013.png
  5. (可选)自定义 OAuth consent screen .

    可以随时更新和自定义 OAuth consent screen .你可以把你的标志,应用名称,TOS等等放在这里。

    ../../_images/google_api_console014.png

配置geoserver oauth2筛选器

  1. 启动geoserver并以 admin 用户。

  2. 单击 Authentication 链接位于 Security 导航边栏的部分。

    ../../_images/filter1.jpg
  3. 向下滚动到 Authentication Filters 面板并单击 Add new 链接。

    ../../_images/filter2.jpg
  4. 单击 OAuth2 链接。

    ../../_images/filter3.jpg
  5. 按如下方式填写设置表单的字段:

    ../../_images/oauth2chain001.png

    插件提供的默认值对Google OAuth2提供程序有效,如下所示:

    "Enable Redirect Authentication EntryPoint" = False
    "Access Token URI" = https://accounts.google.com/o/oauth2/token
    "User Authorization URI" = https://accounts.google.com/o/oauth2/auth
    "Redirect URI" = http://localhost:8080/geoserver
    "Check Token Endpoint URL" = https://www.googleapis.com/oauth2/v1/tokeninfo
    "Logout URI" = https://accounts.google.com/logout
    "Scopes" = https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/userinfo.profile
    

    备注

    1. Client IDClient Secret 是谷歌提供的吗

    2. 选择一个 Role Service 能够将用户电子邮件识别为ID。默认情况下,连接的用户将 ROLE_USER 角色

    警告

    几句话 启用重定向身份验证入口点 选项

    此选项允许您决定是否 是否自动重定向到OAuth2访问令牌URI进行身份验证。

    那是什么意思?

    • 启用重定向身份验证入口点 =真

      如果尚未验证(或没有有效的 访问令牌 在查询字符串中提供),此选项将 重定向到OAuth2提供程序登录页。

      这可能会导致不需要的行为,因为它将重写其他所有显式登录方法,如 form . 换句话说,如果过滤器应用于 web 端点,将无法通过浏览器使用标准登录方法访问GeoServer管理GUI。

    • 启用重定向身份验证入口点 =假

      为了避免上述问题,通过禁用此选项,您将 强迫 使用显式身份验证终结点通过OAuth2提供程序登录页登录。

      如果尚未验证(或没有有效的 访问令牌 在查询字符串中提供) must 通过以下URL进行身份验证:

      1. GeoServer OAuth2授权终结点http://<host:port>/geoserver/j_spring_oauth2_login

      2. OAuth2提供程序显式用户授权终结点 ;这必须适合您的特定OAuth2提供者,协议规定它应该

        https://<USER_AUTHORIZATION_URI>?scope=<SCOPES>&response_type=code&redirect_uri=<REDIRECT_URI>&client_id=<CLIENT_ID>
        

        对于Google OAuth2,提供程序是:

        https://accounts.google.com/o/oauth2/auth?scope%3Dhttps://www.googleapis.com/auth/userinfo.email%2Bhttps://www.googleapis.com/auth/userinfo.profile%26response_type%3Dcode%26redirect_uri%3D<REDIRECT_URI>%26client_id%3D<CLIENT_ID>
        
  6. 通过添加新的OAuth2筛选器来更新筛选器链。

    配置完所有内容后,您应该能够看到新的 oauth2 过滤器可用于 Authentication Filters 列表

    ../../_images/oauth2filter001.png

    通过这一点,始终可以修改/更新过滤器选项,或创建更多选项。

    下一步是将过滤器添加到 Filter Chains 你还想用OAuth2来保护

    ../../_images/oauth2filter002.png
  7. 为要使用OAuth2保护的每个筛选器链选择OAuth2筛选器。

    如果你需要保护 all GeoServer服务和GeoServer管理GUI对于OAuth2,还需要添加 oauth2 过滤到以下所有链

    • web

    • rest

    • gwc

    • default

    身份验证筛选器的顺序基本上取决于您希望GeoServer使用哪种方法 先试试看 .

    备注

    在身份验证过程中 Filter Chain 连续执行,直到一个成功为止(有关详细信息,请参阅 身份验证链

    警告

    如果 启用重定向身份验证入口点 = True 对于OAuth2过滤器 web 链将无法通过 form 方法。

    ../../_images/oauth2filter003.png

    备注

    记住 anonymous 过滤器必须始终是最后一个。

  8. 保存。

    ../../_images/oauth2filter004.png

现在可以测试身份验证:

  1. 导航到geoserver主页并注销管理帐户。

  2. 尝试再次登录,您现在应该能够看到外部谷歌登录表单。

    ../../_images/test1.jpg
    ../../_images/test2.jpg
    ../../_images/test3.jpg
    ../../_images/test4.jpg
    ../../_images/test5.jpg

OpenID连接身份验证

openid connect身份验证的工作方式与google(和github)身份验证非常相似,唯一的区别是身份验证页面无法为各个端点建议默认值,这些端点必须手动配置。

如果不使用Web登录,则实际上不需要“客户端ID”和“客户端机密”,并且可以用两个组成的值填充(验证仅检查它们是否存在,但它们将仅用于“授权流”,而不用于在客户端为su的情况下执行ogc请求。已自动检索到有效的不记名令牌)。

配置GUI支持OpenID发现文档。如果服务器支持它们,那么提供文档或身份验证服务根目录的路径就足够了,GUI将根据文档内容自动填充:

../../_images/discovery.png

用户界面还允许设置 Post Logout Redirect URI 它将用于填充 post_logout_redirect_uri 从Geoserver用户界面执行全局注销时的请求参数。OpenID提供程序将使用URI重定向到所需的应用程序页面。

此外,OpenID连接身份验证能够从ID令牌或访问令牌中提取用户角色:

../../_images/openidconnect-roles.png

所选属性必须出现在访问令牌或ID令牌中,并且必须是字符串或字符串数组。

从UI中,还可以设置 Response Mode 价值。此字段可以保留为空,但当作为身份提供者的OpenID服务器默认不将授权码作为查询字符串发送时(这是必需的,以允许Geoserver和OpenID正常集成),则需要此字段。

最后,管理员可以允许在Access_Token请求期间通过 Send Client Secret in Token Request 。当客户端应用程序是机密客户端并且可以安全地存储CLIENT_SECRET时,一些OpenID实现需要它用于授权代码流。

使用附加的访问承载令牌进行OpenID连接

OpenID连接插件允许使用附加的持有者访问令牌。这通常由自动(即桌面或外部Web服务)用来访问Geoserver REST API。

设置过程如下:

  1. 正常设置您的OAuth2 OpenID Connect配置

  2. 在OpenID连接配置屏幕(底部)上,确保选中了允许附加的持有者令牌

  3. 您不能将ID令牌用作附加的持有者令牌的角色源(见下文)

要使用以下功能,请执行以下操作:

  1. 从底层IdP获取访问令牌

  2. 将访问令牌附加到您的HTTP请求标头

Authorization: Bearer <token>

验证访问令牌(JWT);

  1. 访问令牌用于获取“UserInfo”端点。底层IDP将验证令牌(即签名和过期)

  2. 检查令牌的受众是否包含Geoserver配置的客户端ID。这可确保另一个应用程序的访问令牌不会在Geoserver中被不适当地重复使用(参见 AudienceAccessTokenValidator.java )。

  3. 的主题是 userinfo 和访问令牌被验证为约为同一个人。OpenID规范建议检查此选项(参见 SubjectTokenValidator.java )。

对于KeyCloak,考虑使用“UserInfo Endpoint”角色源并将Keyloak配置为将组放置在“UserInfo”中。

对于Azure AD,将Azure配置为允许访问MS Graph API(MemberOf)并使用“Microsoft Graph API(Azure AD)”角色源。

为Azure AD配置“Memberof”(“GroupMember.Read.All”权限)访问;

  1. 转到您在Azure AD中的应用程序(在门户中)

  2. 在左侧,进入“API权限”。

  3. 点击“添加权限”

  4. 按“Microsoft Graph”

  5. 按“委派的权限”

  6. 向下滚动到“GroupMember”

  7. 选择“组成员.Read.All”

  8. 按“添加权限”

  9. 在API权限屏幕上,按“授予管理员同意...”文本

这已经通过KeyCloak进行了测试(在 userinfo 端点响应),以及MS Azure AD(来自GraphAPI的组)。这应该适用于其他国内流离失所者-但是,请确保主体和受众令牌验证与他们的令牌一起工作。

如果您不需要不记名令牌功能,建议将其关闭。

Azure AD和ADFS设置

要使OpenIdConnect筛选器通过OpenID协议与Azure AD或ADFS服务器一起正常工作,除了其他配置参数外,用户还必须设置 Response Mode 查询(否则,默认情况下,ADFS将返回URL片段)并选中该复选框 Send Client Secret in Token Request (根据令牌请求,CLIENT_SECRET是必需的 Microsoft documentation )。

../../_images/adfs-setup.png

SSL可信证书

使用自定义时 Keystore 或者尝试从非ssh连接访问不受信任或自签名的ssl保护的oauth2提供程序,则需要将证书添加到jvm Keystore .

为此,您可以执行以下步骤:

在这个例子中,我们将

  1. 从Google域检索SSL证书:

    “访问令牌URI”=https://accounts.google.com/o/oauth2/token因此我们需要信任 https://accounts.google.com 或 (accounts.google.com:443 )“检查令牌终结点URL”=https://www.googleapis.com/oauth2/v1/tokeninfo因此我们需要信任 https://www.googleapis.com 或 (www.googleapis.com:443

    备注

    您需要从oauth2端点上使用的每个不同的https url获取并信任证书。

  2. 在本地硬盘上存储SSL证书

  3. 将SSL证书添加到Java密钥库

  4. 允许JVM检查密钥库中的SSL证书

  1. 从Google域中检索SSL证书

    使用 openssl 命令以转储证书

    为了 https://accounts.google.com

    openssl s_client -connect accounts.google.com:443
    
    ../../_images/google_ssl_001.png

    为了 https://www.googleapis.com

    openssl s_client -connect www.googleapis.com:443
    
    ../../_images/google_ssl_002.png
  2. 在本地硬盘上存储SSL证书

    复制并粘贴这两个部分 -BEGIN CERTIFICATE--END CERTIFICATE- 把它们保存成两个不同的 .cert 文件夹

    备注

    .cert 文件是纯文本文件,包含 -BEGIN CERTIFICATE--END CERTIFICATE- 部分

    google.cert (或者你想用什么名字 .cert 扩展名)

    ../../_images/google_ssl_003.png

    google-apis.cert (或者你想用什么名字 .cert 扩展名)

    ../../_images/google_ssl_004.png
  3. 将SSL证书添加到Java密钥库

    您可以使用java命令 keytool 这样地

    google.cert (或者你想用什么名字 .cert 扩展名)

    keytool -import -noprompt -trustcacerts -alias google -file google.cert -keystore ${KEYSTOREFILE} -storepass ${KEYSTOREPASS}
    

    google-apis.cert (或者你想用什么名字 .cert 扩展名)

    keytool -import -noprompt -trustcacerts -alias google-apis -file google-apis.cert -keystore ${KEYSTOREFILE} -storepass ${KEYSTOREPASS}
    

    或者,您也可以使用一些图形工具来帮助您管理ssl证书和密钥库,比如 Portecle

    java -jar c:\apps\portecle-1.9\portecle.jar
    
    ../../_images/google_ssl_005.png
    ../../_images/google_ssl_006.png
    ../../_images/google_ssl_007.png
    ../../_images/google_ssl_008.png
    ../../_images/google_ssl_009.png
    ../../_images/google_ssl_010.png
    ../../_images/google_ssl_011.png
    ../../_images/google_ssl_012.png
    ../../_images/google_ssl_013.png
  4. 允许JVM检查密钥库中的SSL证书

    为了做到这一点,你需要通过 JAVA_OPTION 对于您的jvm:

    -Djavax.net.ssl.trustStore=F:\tmp\keystore.key
    
  5. 重新启动服务器

备注

下面您可以找到一个bash脚本,它简化了密钥库SSL证书的导入。在你方便的时候使用它。

HOST=myhost.example.com
PORT=443
KEYSTOREFILE=dest_keystore
KEYSTOREPASS=changeme

# get the SSL certificate
openssl s_client -connect ${HOST}:${PORT} </dev/null \
        | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ${HOST}.cert

# create a keystore and import certificate
keytool -import -noprompt -trustcacerts \
        -alias ${HOST} -file ${HOST}.cert \
        -keystore ${KEYSTOREFILE} -storepass ${KEYSTOREPASS}

# verify we've got it.
keytool -list -v -keystore ${KEYSTOREFILE} -storepass ${KEYSTOREPASS} -alias ${HOST}