Base solution for your next web application
Open Closed

Setting 'Should change password on next login' caused infinite reset-password loop #11543


User avatar
0
hongbing.wang created

Hi Support team,

WMS Pro 1.0.66166 Standard | API: v12.0.0 | Client: v12.0.0 [20230123]

Steps to reproduce the issue:

Menu, Admin > User, edit a user, tick 'Should change password on next login' and save. Logout and Login as the edited user. It keeps reloading http://localhost:4200/account/reset-password?tenantId=1&c=G%2FjWWUr9SDq6drYGk37O9kgUKtvmi8VQYMT0O1DB97ztLA%2F%2BjWBPa3g4OLP3j8ffTTyX3D3Ol5CNbBn5xiPTwy17sLV3eK9c4UD%2BOcgSjjA%3D Hence change-password modal dialog kept flashing.

Possible cause: AbpSession.TenantId is not null, tenant is not null, isCurrentTenant returns false, hence the infinite loop of reset-password - location.reload() in src\shared\common\session\app-session.service.ts.

src\shared\common\session\app-session.service.ts:

private isCurrentTenant(tenantId?: number) {
    let isTenant = tenantId > 0;

    if (!isTenant && !this.tenant) {
        // this is host
        return true;
    }

    if (!tenantId && this.tenant) {
        return false;
    } else if (tenantId && (!this.tenant || this.tenant.id !== tenantId)) {
        return false;
    }

    return true;
}

Your sample app works without the issue because AbpSession.TenantId is null, tenant is null, isCurrentTenant returns true, so no such a problem.

See GetCurrentLoginInformations in aspnet-core\src\umsplus.Application\Sessions\SessionAppService.cs if (AbpSession.TenantId.HasValue) { output.Tenant = await GetTenantLoginInfo(AbpSession.GetTenantId()); }

src\shared\common\session\app-session.service.ts:

changeTenantIfNeeded(tenantId?: number): boolean {
    if (this.isCurrentTenant(tenantId)) {
        return false;
    }

    abp.multiTenancy.setTenantIdCookie(tenantId);
    location.reload();
    return true;
}

src\account\password\reset-password.component.ts:

ngOnInit(): void {
    this._profileService.getPasswordComplexitySetting().subscribe((result) => {
        this.passwordComplexitySetting = result.setting;
    });

    if (this._activatedRoute.snapshot.queryParams['c']) {
        this.model.c = this._activatedRoute.snapshot.queryParams['c'];

        this._accountService
            .resolveTenantId(new ResolveTenantIdInput({ c: this.model.c }))
            .subscribe((tenantId) => {
                this.appSession.changeTenantIfNeeded(tenantId);
            });
    } else {
        this.model.userId = this._activatedRoute.snapshot.queryParams['userId'];
        this.model.resetCode = this._activatedRoute.snapshot.queryParams['resetCode'];

        this.appSession.changeTenantIfNeeded(
            this.parseTenantId(this._activatedRoute.snapshot.queryParams['tenantId'])
        );
    }
}

src\shared\common\session\app-session.service.ts:

private isCurrentTenant(tenantId?: number) {
    let isTenant = tenantId > 0;

    if (!isTenant && !this.tenant) {
        // this is host
        return true;
    }

    if (!tenantId && this.tenant) {
        return false;
    } else if (tenantId && (!this.tenant || this.tenant.id !== tenantId)) {
        return false;
    }

    return true;
}

ResolveTenantIdInput input is c: G/jWWUr9SDq6drYGk37O9kgUKtvmi8VQYMT0O1DB97ztLA/+jWBPa3g4OLP3j8ffTTyX3D3Ol5CNbBn5xiPTwy17sLV3eK9c4UD+OcgSjjA= Decrypt it the parameters are userId=6&resetCode=8C0780EE88&expireDate=2023-04-13T14%3A51%3A45%2B10%3A00 This will result in ResolveTenantId null. Is this intended?

webapi\src\umsplus.Application\Authorization\Accounts\AccountAppService.cs public Task<int?> ResolveTenantId(ResolveTenantIdInput input) { if (string.IsNullOrEmpty(input.c)) { return Task.FromResult(AbpSession.TenantId); }

        var parameters = SimpleStringCipher.Instance.Decrypt(input.c);
        var query = HttpUtility.ParseQueryString(parameters);

        if (query["tenantId"] == null)
        {
            return Task.FromResult&lt;int?&gt;(null);
        }

        var tenantId = Convert.ToInt32(query["tenantId"]) as int?;
        return Task.FromResult(tenantId);
    }

I would think in our case GetCurrentLoginInformations with tenant info is OK. Can we modify isCurrentTenant()? Or I missed something? Looking forward to hearing from you. Thanks for your support.


1 Answer(s)