openmetadata单点登录集成

openmetadata单点登录集成

Openmetadata集成第三方认证服务实现单点登录认证

原理:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

oidc 授权码模式认证流程

  1. OM调用接口获取oidc想过认证接口配置信息

http://localhost:8111/.well-known/openid-configuration

image-20240411170319683

  1. OM应用向oidc服务请求授权码:

http://localhost:8111/oauth2/authorize?client_id=openmetadata&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&response_type=code&scope=openid%20email%20profile&state=92c4d3388bbb4c7496376b1f1386a054&code_challenge=Wo9na1uLrQTI_8rVPQLjqDDG-mT6ii1zVxbRvIML2C4&code_challenge_method=S256&response_mode=query

  1. oidc服务转发调用idaas认证服务获取code:

http://login-iam.jn-sit.ieccloud.hollicube.com/oauth/authorize?response_type=code&client_id=openmetadata&redirect_uri=http://localhost:8111/callback&state=92c4d3388bbb4c7496376b1f1386a054

  1. idaas认证服务获取session信息判断用户是否登录,若未登录跳转登录页面登录。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 登陆成功后根据回调地址回调并返回code和state状态码:

http://localhost:8111/callback?code=FJIXwO&state=92c4d3388bbb4c7496376b1f1386a054

  1. oidc服务将code和state码转发给OM服务回调地址

http://localhost:3000/callback?state=92c4d3388bbb4c7496376b1f1386a054&code=FJIXwO

  1. OM服务获取调用oidc服务 token认证接口验证code并获取token

http://localhost:8111/authorize/token?client_id=openmetadata&code=FJIXwO&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&code_verifier=c8665192f96a46f1852a53afba7b2e8a9504a757fb4644c49cc0bc230693db7d58dd09fd809046928d6222400c711091&grant_type=authorization_code

  1. oidc服务处理并转发请求,调用idaas认证服务token接口获取用户登录access_token、refresh_token信息:

http://login-iam.jn-sit.ieccloud.hollicube.com/oauth/token?grant_type=authorization_code&client_id={client_id}&client_secret={app.secret_key}&code={code}&redirect_uri={redirect_uri}

  1. idaas认证服返回token信息,oidc服务处理返回的token信息,并创建id_token返回:(token包含公钥和秘钥信息)

http://localhost:8111/authorize/token

返回参数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. OM服务将id_token存储到head Authorization中,并调用token验证接口验证jwt token合法性及解密用户信息并返回:(OM调用秘钥解码验证合法性)

http://localhost:3000/api/v1/users/loggedInUser?fields=profile%2Cteams%2Croles%2Cpersonas%2CdefaultPersona

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接口返回的用户信息

image-20240411165814344

  1. OM认证通过,解析用户信息,登陆(若该用户未登录则跳转注册页面),并进入用户页面:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

源码实现

  1. OM修改配置文件

conf/openmetadata.yaml

#  Copyright 2021 Collate
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#  http://www.apache.org/licenses/LICENSE-2.0
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

clusterName: ${OPENMETADATA_CLUSTER_NAME:-openmetadata}

swagger:
  resourcePackage: org.openmetadata.service.resources

server:
  rootPath: '/api/*'
  applicationConnectors:
    - type: http
      port: ${SERVER_PORT:-8585}
  adminConnectors:
    - type: http
      port: ${SERVER_ADMIN_PORT:-8586}

# Logging settings.
# https://logback.qos.ch/manual/layouts.html#conversionWord
logging:
  level: ${LOG_LEVEL:-INFO}
  loggers:
    org.openmetadata.service.util.OpenMetadataSetup:
      level: INFO
      appenders:
        - type: console
          logFormat: "%msg%n"
          timeZone: UTC
        - type: file
          logFormat: "%level [%d{ISO8601,UTC}] [%t] %logger{5} - %msg%n"
          layout:
            type: json
          currentLogFilename: ./logs/openmetadata-operations.log
          archivedLogFilenamePattern: ./logs/openmetadata-operations-%d{yyyy-MM-dd}-%i.log.gz
          archivedFileCount: 7
          timeZone: UTC
          maxFileSize: 50MB
  appenders:
    - type: console
      threshold: TRACE
      logFormat: "%level [%d{ISO8601,UTC}] [%t] %logger{5} - %msg%n"
      timeZone: UTC
    - type: file
      layout:
        type: json
        appendLineSeparator: true
      filterFactories:
        - type: audit-exclude-filter-factory
      threshold: TRACE
      logFormat: "%level [%d{ISO8601,UTC}] [%t] %logger{5} - %msg%n"
      currentLogFilename: ./logs/openmetadata.log
      archivedLogFilenamePattern: ./logs/openmetadata-%d{yyyy-MM-dd}-%i.log.gz
      archivedFileCount: 7
      timeZone: UTC
      maxFileSize: 50MB
    - type: file
      layout:
        type: json
        appendLineSeparator: true
      filterFactories:
        - type: audit-only-filter-factory
      threshold: TRACE
      logFormat: "%level [%d{ISO8601,UTC}] [%t] %logger{5} - %msg%n"
      currentLogFilename: ./logs/audit.log
      archivedLogFilenamePattern: ./logs/audit-%d{yyyy-MM-dd}-%i.log.gz
      archivedFileCount: 25
      timeZone: UTC
      maxFileSize: 50MB

database:
  # the name of the JDBC driver, mysql in our case
  driverClass: ${DB_DRIVER_CLASS:-org.postgresql.Driver}
  #${DB_DRIVER_CLASS:-com.mysql.cj.jdbc.Driver}
  # the username and password
  user: ${DB_USER:-openmetadata_user}
  password: ${DB_USER_PASSWORD:-openmetadata_password}
  # the JDBC URL; the database is called openmetadata_db
  url: jdbc:postgresql://127.0.0.1:5432/openmetadata_db?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC
  #jdbc:${DB_SCHEME:-mysql}://${DB_HOST:-localhost}:${DB_PORT:-3306}/${OM_DATABASE:-openmetadata_db}?${DB_PARAMS:-allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC}

migrationConfiguration:
  flywayPath: "./bootstrap/sql/migrations/flyway"
  nativePath: "./bootstrap/sql/migrations/native"
  extensionPath: ""

# Authorizer Configuration
authorizerConfiguration:
  className: ${AUTHORIZER_CLASS_NAME:-org.openmetadata.service.security.DefaultAuthorizer}
  containerRequestFilter: ${AUTHORIZER_REQUEST_FILTER:-org.openmetadata.service.security.JwtFilter}
  #adminPrincipals: ${AUTHORIZER_ADMIN_PRINCIPALS:-[admin]}
  adminPrincipals:
    - "admin-user"
    - "admin"
  allowedEmailRegistrationDomains: ${AUTHORIZER_ALLOWED_REGISTRATION_DOMAIN:-["all"]}
  principalDomain: ${AUTHORIZER_PRINCIPAL_DOMAIN:-"hollysys.com"}
  enforcePrincipalDomain: ${AUTHORIZER_ENFORCE_PRINCIPAL_DOMAIN:-false}
  enableSecureSocketConnection : ${AUTHORIZER_ENABLE_SECURE_SOCKET:-false}

authenticationConfiguration:
#  provider: ${AUTHENTICATION_PROVIDER:-basic}
#  # This is used by auth provider provide response as either id_token or code
#  responseType: ${AUTHENTICATION_RESPONSE_TYPE:-id_token}
#  # This will only be valid when provider type specified is customOidc
#  providerName: ${CUSTOM_OIDC_AUTHENTICATION_PROVIDER_NAME:-""}
#  publicKeyUrls: ${AUTHENTICATION_PUBLIC_KEYS:-[http://localhost:8585/api/v1/system/config/jwks]}
#  authority: ${AUTHENTICATION_AUTHORITY:-https://accounts.google.com}
#  clientId: ${AUTHENTICATION_CLIENT_ID:-""}
#  callbackUrl: ${AUTHENTICATION_CALLBACK_URL:-""}
#  jwtPrincipalClaims: ${AUTHENTICATION_JWT_PRINCIPAL_CLAIMS:-[email,preferred_username,sub]}
#  enableSelfSignup : ${AUTHENTICATION_ENABLE_SELF_SIGNUP:-true}
  provider: "custom-oidc"
  providerName: "KeyCloak"
  responseType: "code" #${AUTHENTICATION_RESPONSE_TYPE:-id_token}
  publicKeyUrls:
    #    - "http://localhost:8081/realms/data-sec/protocol/openid-connect/certs"
    - "http://localhost:8111/oauth2/keys"
    - "http://localhost:8585/api/v1/system/config/jwks" # Update with your Domain and Make sure this "/api/v1/config/jwks" is always configured to enable JWT tokens
  #  authority: "http://localhost:8081/realms/data-sec"
  authority: "http://localhost:8111"
  #  clientId: "open-metadata"
  clientId: "openmetadata"
  #  callbackUrl: "http://localhost:8585/callback"
  callbackUrl: "http://localhost:8111/callback"
  jwtPrincipalClaims: [email,preferred_username,sub] #${AUTHENTICATION_JWT_PRINCIPAL_CLAIMS:-[email,preferred_username,sub]}
  enableSelfSignup : ${AUTHENTICATION_ENABLE_SELF_SIGNUP:-true}
  samlConfiguration:
    debugMode: ${SAML_DEBUG_MODE:-false}
    idp:
      entityId: ${SAML_IDP_ENTITY_ID:-""}
      ssoLoginUrl: ${SAML_IDP_SSO_LOGIN_URL:-""}
      idpX509Certificate: ${SAML_IDP_CERTIFICATE:-""}
      authorityUrl: ${SAML_AUTHORITY_URL:-"http://localhost:8585/api/v1/saml/login"}
      nameId: ${SAML_IDP_NAME_ID:-"urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress"}
    sp:
      entityId: ${SAML_SP_ENTITY_ID:-"http://localhost:8585/api/v1/saml/metadata"}
      acs: ${SAML_SP_ACS:-"http://localhost:8585/api/v1/saml/acs"}
      spX509Certificate: ${SAML_SP_CERTIFICATE:-""}
      callback: ${SAML_SP_CALLBACK:-"http://localhost:8585/saml/callback"}
    security:
      strictMode: ${SAML_STRICT_MODE:-false}
      tokenValidity: ${SAML_SP_TOKEN_VALIDITY:-"3600"}
      sendEncryptedNameId: ${SAML_SEND_ENCRYPTED_NAME_ID:-false}
      sendSignedAuthRequest: ${SAML_SEND_SIGNED_AUTH_REQUEST:-false}
      signSpMetadata: ${SAML_SIGNED_SP_METADATA:-false}
      wantMessagesSigned: ${SAML_WANT_MESSAGE_SIGNED:-false}
      wantAssertionsSigned: ${SAML_WANT_ASSERTION_SIGNED:-false}
      wantAssertionEncrypted: ${SAML_WANT_ASSERTION_ENCRYPTED:-false}
      wantNameIdEncrypted: ${SAML_WANT_NAME_ID_ENCRYPTED:-false}
      keyStoreFilePath: ${SAML_KEYSTORE_FILE_PATH:-""}
      keyStoreAlias: ${SAML_KEYSTORE_ALIAS:-""}
      keyStorePassword: ${SAML_KEYSTORE_PASSWORD:-""}
  ldapConfiguration:
    host: ${AUTHENTICATION_LDAP_HOST:-}
    port: ${AUTHENTICATION_LDAP_PORT:-}
    dnAdminPrincipal: ${AUTHENTICATION_LOOKUP_ADMIN_DN:-""}
    dnAdminPassword: ${AUTHENTICATION_LOOKUP_ADMIN_PWD:-""}
    userBaseDN: ${AUTHENTICATION_USER_LOOKUP_BASEDN:-""}
    groupBaseDN: ${AUTHENTICATION_GROUP_LOOKUP_BASEDN:-""}
    roleAdminName: ${AUTHENTICATION_USER_ROLE_ADMIN_NAME:-}
    allAttributeName: ${AUTHENTICATION_USER_ALL_ATTR:-}
    mailAttributeName: ${AUTHENTICATION_USER_MAIL_ATTR:-}
    usernameAttributeName: ${AUTHENTICATION_USER_NAME_ATTR:-}
    groupAttributeName: ${AUTHENTICATION_USER_GROUP_ATTR:-}
    groupAttributeValue: ${AUTHENTICATION_USER_GROUP_ATTR_VALUE:-}
    groupMemberAttributeName: ${AUTHENTICATION_USER_GROUP_MEMBER_ATTR:-}
    #the mapping of roles to LDAP groups
    authRolesMapping: ${AUTH_ROLES_MAPPING:-""}
    authReassignRoles: ${AUTH_REASSIGN_ROLES:-[]}
    #optional
    maxPoolSize: ${AUTHENTICATION_LDAP_POOL_SIZE:-3}
    sslEnabled: ${AUTHENTICATION_LDAP_SSL_ENABLED:-}
    truststoreConfigType: ${AUTHENTICATION_LDAP_TRUSTSTORE_TYPE:-TrustAll}
    trustStoreConfig:
      customTrustManagerConfig:
        trustStoreFilePath: ${AUTHENTICATION_LDAP_TRUSTSTORE_PATH:-}
        trustStoreFilePassword: ${AUTHENTICATION_LDAP_KEYSTORE_PASSWORD:-}
        trustStoreFileFormat: ${AUTHENTICATION_LDAP_SSL_KEY_FORMAT:-}
        verifyHostname: ${AUTHENTICATION_LDAP_SSL_VERIFY_CERT_HOST:-}
        examineValidityDates: ${AUTHENTICATION_LDAP_EXAMINE_VALIDITY_DATES:-}
      hostNameConfig:
        allowWildCards: ${AUTHENTICATION_LDAP_ALLOW_WILDCARDS:-}
        acceptableHostNames: ${AUTHENTICATION_LDAP_ALLOWED_HOSTNAMES:-[]}
      jvmDefaultConfig:
        verifyHostname: ${AUTHENTICATION_LDAP_SSL_VERIFY_CERT_HOST:-}
      trustAllConfig:
        examineValidityDates: ${AUTHENTICATION_LDAP_EXAMINE_VALIDITY_DATES:-true}

jwtTokenConfiguration:
  rsapublicKeyFilePath: ${RSA_PUBLIC_KEY_FILE_PATH:-"./conf/key/public_key.der"}
  rsaprivateKeyFilePath: ${RSA_PRIVATE_KEY_FILE_PATH:-"./conf/key/private_key.der"}
  jwtissuer: ${JWT_ISSUER:-"http://iam.jn-sit.ieccloud.hollicube.com/"}
  keyId: ${JWT_KEY_ID:-"Gb389a-9f76-gdjs-a92j-0242bk94356"}

elasticsearch:
  searchType: ${SEARCH_TYPE:- "elasticsearch"}
  host: ${ELASTICSEARCH_HOST:-localhost}
  port: ${ELASTICSEARCH_PORT:-9200}
  scheme: ${ELASTICSEARCH_SCHEME:-http}
  username: ${ELASTICSEARCH_USER:-""}
  password: ${ELASTICSEARCH_PASSWORD:-""}
  clusterAlias: ${ELASTICSEARCH_CLUSTER_ALIAS:-""}
  truststorePath: ${ELASTICSEARCH_TRUST_STORE_PATH:-""}
  truststorePassword: ${ELASTICSEARCH_TRUST_STORE_PASSWORD:-""}
  connectionTimeoutSecs: ${ELASTICSEARCH_CONNECTION_TIMEOUT_SECS:-5}
  socketTimeoutSecs: ${ELASTICSEARCH_SOCKET_TIMEOUT_SECS:-60}
  keepAliveTimeoutSecs: ${ELASTICSEARCH_KEEP_ALIVE_TIMEOUT_SECS:-600}
  batchSize: ${ELASTICSEARCH_BATCH_SIZE:-10}
  searchIndexMappingLanguage : ${ELASTICSEARCH_INDEX_MAPPING_LANG:-EN}
  searchIndexFactoryClassName : org.openmetadata.service.search.SearchIndexFactory

eventMonitoringConfiguration:
  eventMonitor: ${EVENT_MONITOR:-prometheus}  # Possible values are "prometheus", "cloudwatch"
  batchSize: ${EVENT_MONITOR_BATCH_SIZE:-10}
  pathPattern: ${EVENT_MONITOR_PATH_PATTERN:-["/api/v1/tables/*", "/api/v1/health-check"]}
  latency: ${EVENT_MONITOR_LATENCY:-[]} # For value p99=0.99, p90=0.90, p50=0.50 etc.
  # it will use the default auth provider for AWS services if parameters are not set
  # parameters:
  #   region: ${OM_MONITOR_REGION:-""}
  #   accessKeyId: ${OM_MONITOR_ACCESS_KEY_ID:-""}
  #   secretAccessKey: ${OM_MONITOR_ACCESS_KEY:-""}

eventHandlerConfiguration:
  eventHandlerClassNames:
    - "org.openmetadata.service.events.AuditEventHandler"
    - "org.openmetadata.service.events.ChangeEventHandler"
    - "org.openmetadata.service.events.WebAnalyticEventHandler"

pipelineServiceClientConfiguration:
  enabled: ${PIPELINE_SERVICE_CLIENT_ENABLED:-true}
  # If we don't need this, set "org.openmetadata.service.clients.pipeline.noop.NoopClient"
  className: ${PIPELINE_SERVICE_CLIENT_CLASS_NAME:-"org.openmetadata.service.clients.pipeline.airflow.AirflowRESTClient"}
  apiEndpoint: ${PIPELINE_SERVICE_CLIENT_ENDPOINT:-http://host.docker.internal:8080}
  metadataApiEndpoint: ${SERVER_HOST_API_URL:-http://host.docker.internal:8585/api}
  ingestionIpInfoEnabled: ${PIPELINE_SERVICE_IP_INFO_ENABLED:-false}
  hostIp: ${PIPELINE_SERVICE_CLIENT_HOST_IP:-""}
  healthCheckInterval: ${PIPELINE_SERVICE_CLIENT_HEALTH_CHECK_INTERVAL:-300}
  # This SSL information is about the OpenMetadata server.
  # It will be picked up from the pipelineServiceClient to use/ignore SSL when connecting to the OpenMetadata server.
  verifySSL: ${PIPELINE_SERVICE_CLIENT_VERIFY_SSL:-"no-ssl"} # Possible values are "no-ssl", "ignore", "validate"
  sslConfig:
    certificatePath: ${PIPELINE_SERVICE_CLIENT_SSL_CERT_PATH:-""} # Local path for the Pipeline Service Client

  # Secrets Manager Loader: specify to the Ingestion Framework how to load the SM credentials from its env
  # Supported: noop, airflow, env
  secretsManagerLoader: ${PIPELINE_SERVICE_CLIENT_SECRETS_MANAGER_LOADER:-"noop"}

  # Default required parameters for Airflow as Pipeline Service Client
  parameters:
    username: ${AIRFLOW_USERNAME:-admin}
    password: ${AIRFLOW_PASSWORD:-admin}
    timeout: ${AIRFLOW_TIMEOUT:-10}
    # If we need to use SSL to reach Airflow
    truststorePath: ${AIRFLOW_TRUST_STORE_PATH:-""}
    truststorePassword: ${AIRFLOW_TRUST_STORE_PASSWORD:-""}

# no_encryption_at_rest is the default value, and it does what it says. Please read the manual on how
# to secure your instance of OpenMetadata with TLS and encryption at rest.
fernetConfiguration:
  fernetKey: ${FERNET_KEY:-jJ/9sz0g0OHxsfxOoSfdFdmk3ysNmPRnH3TUAbz3IHA=}

secretsManagerConfiguration:
  secretsManager: ${SECRET_MANAGER:-db} # Possible values are "db", "managed-aws", "managed-aws-ssm"
  prefix: ${SECRET_MANAGER_PREFIX:-""} # Define the secret key ID as /<prefix>/<clusterName>/<key>
  tags: ${SECRET_MANAGER_TAGS:-[]} # Add tags to the created resource. Format is `[key1:value1,key2:value2,...]`
  # it will use the default auth provider for the secrets' manager service if parameters are not set
  parameters:
    ## For AWS
    region: ${OM_SM_REGION:-""}
    accessKeyId: ${OM_SM_ACCESS_KEY_ID:-""}
    secretAccessKey: ${OM_SM_ACCESS_KEY:-""}
    ## For Azure Key Vault
    clientId: ${OM_SM_CLIENT_ID:-""}
    clientSecret: ${OM_SM_CLIENT_SECRET:-""}
    tenantId: ${OM_SM_TENANT_ID:-""}
    vaultName: ${OM_SM_VAULT_NAME:-""}

health:
  delayedShutdownHandlerEnabled: true
  shutdownWaitPeriod: 1s
  healthChecks:
    - name: OpenMetadataServerHealthCheck
      critical: true
      schedule:
        checkInterval: 2500ms
        downtimeInterval: 10s
        failureAttempts: 2
        successAttempts: 1

email:
  emailingEntity: ${OM_EMAIL_ENTITY:-"OpenMetadata"}
  supportUrl: ${OM_SUPPORT_URL:-"https://slack.open-metadata.org"}
  enableSmtpServer : ${AUTHORIZER_ENABLE_SMTP:-false}
  openMetadataUrl: ${OPENMETADATA_SERVER_URL:-"http://localhost:8585"}
  senderMail: ${OPENMETADATA_SMTP_SENDER_MAIL:-""}
  serverEndpoint: ${SMTP_SERVER_ENDPOINT:-""}
  serverPort: ${SMTP_SERVER_PORT:-""}
  username: ${SMTP_SERVER_USERNAME:-""}
  password: ${SMTP_SERVER_PWD:-""}
  transportationStrategy: ${SMTP_SERVER_STRATEGY:-"SMTP_TLS"}

web:
  uriPath: ${WEB_CONF_URI_PATH:-"/api"}
  hsts:
    enabled: ${WEB_CONF_HSTS_ENABLED:-false}
    maxAge: ${WEB_CONF_HSTS_MAX_AGE:-"365 days"}
    includeSubDomains: ${WEB_CONF_HSTS_INCLUDE_SUBDOMAINS:-"true"}
    preload: ${WEB_CONF_HSTS_PRELOAD:-"true"}
  frame-options:
    enabled: ${WEB_CONF_FRAME_OPTION_ENABLED:-false}
    option: ${WEB_CONF_FRAME_OPTION:-"SAMEORIGIN"}
    origin: ${WEB_CONF_FRAME_ORIGIN:-""}
  content-type-options:
    enabled: ${WEB_CONF_CONTENT_TYPE_OPTIONS_ENABLED:-false}
  xss-protection:
    enabled: ${WEB_CONF_XSS_PROTECTION_ENABLED:-false}
    on: ${WEB_CONF_XSS_PROTECTION_ON:-true}
    block: ${WEB_CONF_XSS_PROTECTION_BLOCK:-true}
  csp:
    enabled: ${WEB_CONF_XSS_CSP_ENABLED:-false}
    policy: ${WEB_CONF_XSS_CSP_POLICY:-"default-src 'self'"}
    reportOnlyPolicy: ${WEB_CONF_XSS_CSP_REPORT_ONLY_POLICY:-""}
  referrer-policy:
    enabled: ${WEB_CONF_REFERRER_POLICY_ENABLED:-false}
    option: ${WEB_CONF_REFERRER_POLICY_OPTION:-"SAME_ORIGIN"}
  permission-policy:
    enabled: ${WEB_CONF_PERMISSION_POLICY_ENABLED:-false}
    option: ${WEB_CONF_PERMISSION_POLICY_OPTION:-""}

dataQualityConfiguration:
  severityIncidentClassifier: ${DATA_QUALITY_SEVERITY_INCIDENT_CLASSIFIER:-"org.openmetadata.service.util.incidentSeverityClassifier.LogisticRegressionIncidentSeverityClassifier"}

  1. OIDC认证服务源码:

forwarding_service.py

import json
import time
import requests
import jwt
from flask import Flask, redirect, request, jsonify, make_response
from flask_cors import CORS
import base64
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

app = Flask(__name__)
CORS(app)


# 公钥接口
@app.route("/oauth2/keys")
def openid_publicKey():
    # 构建自定义的OIDC配置信息
    with open("./public_jwt_keys.json", 'r') as file:
        jwts = json.load(file)
    # 返回JSON响应
    return jsonify(jwts)

# oidc config查询接口
@app.route("/.well-known/openid-configuration")
def openid_configuration():
    # 构建自定义的OIDC配置信息
    with open("./code-configuration.json", 'r') as file:
        config = json.load(file)
    # 返回JSON响应
    return jsonify(config)

# code认证请求转发
@app.route('/oauth2/authorize', methods=['GET'])
def forward_request_endpoint():
    # 获取原始请求的参数
    original_params = request.args.to_dict()
    # 修改原始请求的参数
    modified_params = original_params.copy()  # 复制原始参数
    modified_params['response_type'] = 'code'  # 修改 response_type 参数为 'token'
    modified_params['scope'] = 'all'
    state = modified_params['state']
    client_id = modified_params['client_id']
    # 定义目标地址
    target_url = f'http://login-iam.jn-sit.ieccloud.hollicube.com/oauth/authorize?response_type=code&client_id={client_id}&redirect_uri=http://localhost:8111/callback&state={state}'
    # 调用转发函数发送修改后的请求,并获取转发后的响应
    print(target_url)
    return redirect(target_url)


# 认证请求转发
@app.route('/callback', methods=['GET'])
def callback_request():
    # 获取请求中的参数
    code = request.args.get('code')
    state = request.args.get('state')
    # 构造重定向地址,将授权信息作为查询参数添加到目标地址
    target_url = 'http://localhost:3000/callback'
    target_url += f'?state={state}&code={code}'
    # 其他参数根据实际情况添加到目标地址的查询字符串中
    response = make_response(redirect(target_url))
    return response


@app.route('/authorize/token', methods=['POST'])
def authorize_token():
    # 获取原始请求的参数
    code = request.form.get('code')  # 获取表单中的参数
    redirect_uri = 'http://localhost:8111/callback'  # request.form.get('redirect_uri')
    client_id = "openmetadata"
    # 客户端请求秘钥
    client_secret='7ed1b43f-331b-838b-bddf-e4a5ca72bae7'
    response = get_token(code, redirect_uri,client_id,client_secret)
    response_json = response.json()
    # 检查响应状态码
    if response.status_code == 200:
        # 请求成功,输出响应内容
        print("POST请求成功!")
        print("响应内容:", response_json)
        access_token = response_json.get("access_token")
        refresh_token = response_json.get("refresh_token")
        realName = response_json.get("realName")
        username = response_json.get("username")
        # 拆分 Access Token
        parts = access_token.split('.')
        # 解码头部和载荷部分
        decoded_header = base64.b64decode(parts[0] + '==').decode('utf-8')
        decoded_payload = base64.b64decode(parts[1] + '==').decode('utf-8')
        print(f'decoded_header:{decoded_header}')
        print(f'decoded_payload:{decoded_payload}')
        iat = int(time.time())
        exp = int(iat + 90000)
        header = {'alg': 'RS256', 'typ': 'JWT', 'kid': 'Gb389a-9f76-gdjs-a92j-0242bk94356'}
        # 读取 DER 格式的私钥文件
        private_key=get_private_key("./key/private_key.der",None)
        # 重构并生成id_token(jwt)
        payload = {
            "iss": "http://iam.jn-sit.ieccloud.hollicube.com/",
            "aud": client_id,
            "sub": username,
            "email": f"{username}@hollicube.com",
            "isBot": "false",
            "iat": iat,
            "preferred_username": realName,
            "name": f'{realName}',
            "user_name": username,
            "exp": exp
        }
        # 编译获取token
        jwt_token = jwt.encode(payload, private_key, algorithm="RS256", headers=header)
        print("Generated JWT token:", jwt_token)
        response_data = {
            "id_token": jwt_token,
            "accessToken": access_token,
            "refreshToken": refresh_token,
            "tokenType": "Bearer",
            "expiryDuration": exp
        }
        return jsonify(response_data), response.status_code
    else:
        # 请求失败,输出失败信息
        print("POST请求失败!")
        print("错误代码:", response.status_code)
        return jsonify(response_json), response.status_code


def get_token(code, redirect_uri, client_id, client_secret):
    client_id = client_id
    get_token_url = f'http://login-iam.jn-sit.ieccloud.hollicube.com/oauth/token?grant_type=authorization_code&client_id={client_id}&client_secret={app.secret_key}&code={code}&redirect_uri={redirect_uri}'
    data = {
        'grant_type': 'authorization_code',
        'client_id': client_id,
        'code': code,
        'redirect_uri': redirect_uri,
        'client_secret': client_secret
    }
    response = requests.post(get_token_url, data=data)
    return response


def get_private_key(filepath, password):
    with open(filepath, "rb") as key_file:
        private_key_data = key_file.read()
        # 加载 DER 格式的私钥
    private_key = serialization.load_der_private_key(
        private_key_data,
        password=password,  # 如果私钥有密码,请在此处提供密码
        backend=default_backend()
    )
    return private_key


if __name__ == '__main__':
    app.run(port=8111)

  1. 获取oidc认证服务配置信息:

code-configuration.json

{
  "issuer": "http://iam.jn-sit.ieccloud.hollicube.com/",
  "authorization_endpoint": "http://localhost:8111/oauth2/authorize",
  "token_endpoint": "http://localhost:8111/authorize/token",
  "userinfo_endpoint": "http://iam.jn-sit.ieccloud.hollicube.com/manage/user/currentUserInfo",
  "revocation_endpoint": "http://iam.jn-sit.ieccloud.hollicube.com/sso/logout",
  "introspection_endpoint": "http://localhost:8111/realms/data-sec/protocol/openid-connect/token/introspect",
  "userinfo_endpoint": "http://localhost:8111/realms/data-sec/protocol/openid-connect/userinfo",
  "end_session_endpoint": "http://iam.jn-sit.ieccloud.hollicube.com/sso/logout",
  "device_authorization_endpoint": "http://login-iam.jn-sit.ieccloud.hollicube.com/oauth2/authorize/device",
  "frontchannel_logout_session_supported": "true",
  "frontchannel_logout_supported": "true",
  "jwks_uri": "http://localhost:8111/oauth2/keys",
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "refresh_token",
    "password",
    "client_credentials",
    "urn:ietf:params:oauth:grant-type:device_code",
    "urn:openid:params:grant-type:ciba"
  ],
  "acr_values_supported": [
    "0",
    "1"
  ],
  "response_types_supported": [
    "code",
    "none",
    "id_token",
    "token",
    "id_token token",
    "code id_token",
    "code token",
    "code id_token token"
  ],
  "subject_types_supported": [
    "public",
    "pairwise"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "id_token_encryption_alg_values_supported": [
    "RSA-OAEP",
    "RSA-OAEP-256",
    "RSA1_5"
  ],
  "id_token_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "userinfo_signing_alg_values_supported": [
    "HS256",
    "RS256",
    "none"
  ],
  "userinfo_encryption_alg_values_supported": [
    "RSA-OAEP",
    "RSA-OAEP-256",
    "RSA1_5"
  ],
  "userinfo_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "request_object_signing_alg_values_supported": [
    "HS256",
    "RS256",
    "none"
  ],
  "request_object_encryption_alg_values_supported": [
    "RSA-OAEP",
    "RSA-OAEP-256",
    "RSA1_5"
  ],
  "request_object_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "response_modes_supported": [
    "query",
    "fragment",
    "form_post",
    "query.jwt",
    "fragment.jwt",
    "form_post.jwt",
    "jwt"
  ],
  "registration_endpoint": "http://localhost:8081/realms/data-sec/clients-registrations/openid-connect",
  "token_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "token_endpoint_auth_signing_alg_values_supported": [
    "HS256",
    "RS256"
  ],
  "introspection_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "introspection_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "authorization_signing_alg_values_supported": [
    "HS256",
    "RS256",
    "none"
  ],
  "authorization_encryption_alg_values_supported": [
    "RSA-OAEP",
    "RSA-OAEP-256",
    "RSA1_5"
  ],
  "authorization_encryption_enc_values_supported": [
    "A128CBC-HS256"
  ],
  "claims_supported": [
    "aud",
    "sub",
    "iss",
    "auth_time",
    "name",
    "given_name",
    "family_name",
    "preferred_username",
    "email",
    "acr"
  ],
  "claim_types_supported": [
    "normal"
  ],
  "claims_parameter_supported": "true",
  "scopes_supported": [
    "openid",
    "acr",
    "microprofile-jwt",
    "roles",
    "address",
    "offline_access",
    "web-origins",
    "profile",
    "phone",
    "email"
  ],
  "request_parameter_supported": "true",
  "request_uri_parameter_supported": "true",
  "require_request_uri_registration": "true",
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ],
  "tls_client_certificate_bound_access_tokens": "true",
  "revocation_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "revocation_endpoint_auth_signing_alg_values_supported": [
    "RS256"
  ],
  "backchannel_logout_supported": "true",
  "backchannel_logout_session_supported": "true",
  "backchannel_token_delivery_modes_supported": [
    "poll",
    "ping"
  ],
  "backchannel_authentication_request_signing_alg_values_supported": [
    "RS256"
  ],
  "require_pushed_authorization_requests": "false"
}

  • 27
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值