fix(oidc): bugs of integration with logto (#2032)
* fix(oidc): iss validate bug * chore: pass iss instend of all values * fix(oidc): use BroadcastChannel & add alg options * chore(oidc): improve
This commit is contained in:
		
							parent
							
								
									47859c0f99
								
							
						
					
					
						commit
						f1feb56743
					
				@ -53,9 +53,6 @@ export const OIDCButton = (props: { authenticator: Authenticator }) => {
 | 
				
			|||||||
      redirect();
 | 
					      redirect();
 | 
				
			||||||
    } catch (err) {
 | 
					    } catch (err) {
 | 
				
			||||||
      console.error(err);
 | 
					      console.error(err);
 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
      windowHandler.close();
 | 
					 | 
				
			||||||
      setWindowHandler(undefined);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,9 +62,10 @@ export const OIDCButton = (props: { authenticator: Authenticator }) => {
 | 
				
			|||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    if (!windowHandler) return;
 | 
					    if (!windowHandler) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    window.addEventListener('message', handleOIDCLogin);
 | 
					    const channel = new BroadcastChannel('nocobase-oidc-response');
 | 
				
			||||||
 | 
					    channel.onmessage = handleOIDCLogin;
 | 
				
			||||||
    return () => {
 | 
					    return () => {
 | 
				
			||||||
      window.removeEventListener('message', handleOIDCLogin);
 | 
					      channel.close();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  }, [windowHandler, handleOIDCLogin]);
 | 
					  }, [windowHandler, handleOIDCLogin]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -39,11 +39,41 @@ const schema = {
 | 
				
			|||||||
            tooltip: '{{t("Default: openid profile email")}}',
 | 
					            tooltip: '{{t("Default: openid profile email")}}',
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        idTokenSignedResponseAlg: {
 | 
				
			||||||
 | 
					          title: '{{t("id_token signed response algorithm")}}',
 | 
				
			||||||
 | 
					          'x-component': 'Select',
 | 
				
			||||||
 | 
					          'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					          enum: [
 | 
				
			||||||
 | 
					            { label: 'HS256', value: 'HS256' },
 | 
				
			||||||
 | 
					            { label: 'HS384', value: 'HS384' },
 | 
				
			||||||
 | 
					            { label: 'HS512', value: 'HS512' },
 | 
				
			||||||
 | 
					            { label: 'RS256', value: 'RS256' },
 | 
				
			||||||
 | 
					            { label: 'RS384', value: 'RS384' },
 | 
				
			||||||
 | 
					            { label: 'RS512', value: 'RS512' },
 | 
				
			||||||
 | 
					            { label: 'ES256', value: 'ES256' },
 | 
				
			||||||
 | 
					            { label: 'ES384', value: 'ES384' },
 | 
				
			||||||
 | 
					            { label: 'ES512', value: 'ES512' },
 | 
				
			||||||
 | 
					            { label: 'PS256', value: 'PS256' },
 | 
				
			||||||
 | 
					            { label: 'PS384', value: 'PS384' },
 | 
				
			||||||
 | 
					            { label: 'PS512', value: 'PS512' },
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        http: {
 | 
					        http: {
 | 
				
			||||||
          title: '{{t("http")}}',
 | 
					          title: '{{t("HTTP")}}',
 | 
				
			||||||
          'x-component': 'Checkbox',
 | 
					          'x-component': 'Checkbox',
 | 
				
			||||||
          'x-decorator': 'FormItem',
 | 
					          'x-decorator': 'FormItem',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        port: {
 | 
				
			||||||
 | 
					          title: '{{t("Port")}}',
 | 
				
			||||||
 | 
					          'x-component': 'InputNumber',
 | 
				
			||||||
 | 
					          'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					          'x-component-props': {
 | 
				
			||||||
 | 
					            style: {
 | 
				
			||||||
 | 
					              width: '15%',
 | 
				
			||||||
 | 
					              'min-width': '100px',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        fieldMap: {
 | 
					        fieldMap: {
 | 
				
			||||||
          title: '{{t("Field Map")}}',
 | 
					          title: '{{t("Field Map")}}',
 | 
				
			||||||
          type: 'array',
 | 
					          type: 'array',
 | 
				
			||||||
 | 
				
			|||||||
@ -5,4 +5,5 @@ export default {
 | 
				
			|||||||
  Edit: '编辑',
 | 
					  Edit: '编辑',
 | 
				
			||||||
  Copied: '已复制',
 | 
					  Copied: '已复制',
 | 
				
			||||||
  'Field Map': '字段映射',
 | 
					  'Field Map': '字段映射',
 | 
				
			||||||
 | 
					  'id_token signed response algorithm': 'id_token签名算法',
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,9 @@ export const redirect = async (ctx: Context, next) => {
 | 
				
			|||||||
    </head>
 | 
					    </head>
 | 
				
			||||||
    <body>
 | 
					    <body>
 | 
				
			||||||
      <script>
 | 
					      <script>
 | 
				
			||||||
        window.opener.postMessage(${JSON.stringify(params)}, '*');
 | 
					        const channel = new BroadcastChannel('nocobase-oidc-response');
 | 
				
			||||||
 | 
					        channel.postMessage(${JSON.stringify(params)})
 | 
				
			||||||
 | 
					        window.close();
 | 
				
			||||||
      </script>
 | 
					      </script>
 | 
				
			||||||
    </body>
 | 
					    </body>
 | 
				
			||||||
    </html>
 | 
					    </html>
 | 
				
			||||||
 | 
				
			|||||||
@ -13,9 +13,10 @@ export class OIDCAuth extends BaseAuth {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  getRedirectUri() {
 | 
					  getRedirectUri() {
 | 
				
			||||||
    const ctx = this.ctx;
 | 
					    const ctx = this.ctx;
 | 
				
			||||||
    const { http } = this.getOptions();
 | 
					    const { http, port } = this.getOptions();
 | 
				
			||||||
    const protocol = http ? 'http' : 'https';
 | 
					    const protocol = http ? 'http' : 'https';
 | 
				
			||||||
    return `${protocol}://${ctx.host}/api/oidc:redirect`;
 | 
					    const host = port ? `${ctx.hostname}${port ? `:${port}` : ''}` : ctx.host;
 | 
				
			||||||
 | 
					    return `${protocol}://${host}/api/oidc:redirect`;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getOptions() {
 | 
					  getOptions() {
 | 
				
			||||||
@ -37,11 +38,12 @@ export class OIDCAuth extends BaseAuth {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async createOIDCClient() {
 | 
					  async createOIDCClient() {
 | 
				
			||||||
    const { issuer, clientId, clientSecret } = this.getOptions();
 | 
					    const { issuer, clientId, clientSecret, idTokenSignedResponseAlg } = this.getOptions();
 | 
				
			||||||
    const oidc = await Issuer.discover(issuer);
 | 
					    const oidc = await Issuer.discover(issuer);
 | 
				
			||||||
    return new oidc.Client({
 | 
					    return new oidc.Client({
 | 
				
			||||||
      client_id: clientId,
 | 
					      client_id: clientId,
 | 
				
			||||||
      client_secret: clientSecret,
 | 
					      client_secret: clientSecret,
 | 
				
			||||||
 | 
					      id_token_signed_response_alg: idTokenSignedResponseAlg || 'RS256',
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,6 +61,7 @@ export class OIDCAuth extends BaseAuth {
 | 
				
			|||||||
    const client = await this.createOIDCClient();
 | 
					    const client = await this.createOIDCClient();
 | 
				
			||||||
    const tokens = await client.callback(this.getRedirectUri(), {
 | 
					    const tokens = await client.callback(this.getRedirectUri(), {
 | 
				
			||||||
      code: values.code,
 | 
					      code: values.code,
 | 
				
			||||||
 | 
					      iss: values.iss,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    const userInfo: { [key: string]: any } = await client.userinfo(tokens.access_token);
 | 
					    const userInfo: { [key: string]: any } = await client.userinfo(tokens.access_token);
 | 
				
			||||||
    const mappedUserInfo = this.mapField(userInfo);
 | 
					    const mappedUserInfo = this.mapField(userInfo);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user