0

Good day,

I have a mobile application and call to mobileFirstPlatform and then only go to my backend service.

I am not sure my understanding is correct or not, in order to call to my Adapter Resource with @OAuthSecurity, I need to authenticate success with mfp first, then only able to access to that resource.

In my mobileFirst Console, I have configure this as my Scope-Elements Mapping and Mandatory Application Scope: enter image description here

The following is part of my frontend code in login.component.ts:

ngOnInit() {
      this.mfpAuthenticationService.initEventHandler();
      this.initAuthHandle();
}

  initAuthHandle() {
    this.authSuccessEventSubscription = this.mfpAuthenticationService.authSuccessEvent.subscribe((loginResponse: any) => {
// do something after success login
});

this.authFailureEventSubscription = this.mfpAuthenticationService.authFailureEvent.subscribe((res: any) => {

      console.log('authFailureEvent => ', res);

      if (res.errorCode == WLErrorCodeConstant.ClientSideError.CHALLENGE_HANDLING_CANCELED && this.mfpAuthenticationService.isBiometricAuthenticated()) {

        return;

      } else {

        this.handleLoginError(res);

        this.loginForm.resetForm();

        this.processLogin = false;

      }

    });

    this.authChallengeEventSubscription = this.mfpAuthenticationService.authChallengeEvent.subscribe((res: any) => {

      console.log('authChallengeEvent => ', res);

      let redirectPath = this.sessionService.getSessionStorage(SessionName.REDIRECT_PATH);

      if (redirectPath) {

        console.log('biometric user login error => ', res);

        this.login.password = null;

        this.isLoginButtonClicked = false;

        this.baseService.handleError(res, true);

      } else {

        this.handleLoginError(res);

      }

      this.loginForm.resetForm();

      this.processLogin = false;

    });
}

performLogin() {
this.mfpAuthenticationService.performLogin(this.login.username, this.loginRequest);
}

And this is some code on mfp.auth.service.ts:

initEventHandler() {
        console.log("come mfp.auth.service.ts initEventhandler");
        this.currentEventHandler = '';
        this.userLoginChallengeHandler = null;
        this.userLoginChallengeHandler = WL.Client.createSecurityCheckChallengeHandler('UserAuthentication');
        this.userLoginChallengeHandler.securityCheckName = '';
        this.userLoginChallengeHandler.handleSuccess = (loginSuccess) => {
            console.log("handleSuccess");
            this.isChallenged = false;
            if (this.currentEventHandler != this.eventHandler.success) {
                this.currentLoginGrantType = this.processLoginGrantType;
                //alert("initEventHandler|loginSuccess=\n" + JSON.stringify(loginSuccess));
                console.log("loginSuccess is " + JSON.stringify(loginSuccess));
                this.mfpAuthResponse = {
                    id: loginSuccess.id,
                    accessToken: loginSuccess.user.attributes.access_token,
                    tokenType: loginSuccess.user.attributes.token_type,
                    expiresIn: loginSuccess.user.attributes.expires_in,
                    scope: loginSuccess.user.attributes.scope,
                    clientId: loginSuccess.user.attributes.client_id
                };
            }
            this.currentEventHandler = this.eventHandler.success;
            console.log("handler success, challenged is " + this.isChallenged);
        };

        this.userLoginChallengeHandler.handleFailure = (loginError) => {
            console.log("handleFailure");
            this.isChallenged = false;
            if (this.currentEventHandler != this.eventHandler.failure) {
                this.authFailureEvent.emit(loginError);
            }
            this.currentEventHandler = this.eventHandler.failure;
            console.log("handleFailure, challenged is " + this.isChallenged);
        };

        this.userLoginChallengeHandler.handleChallenge = (challenge) => {
            console.log("handleChallenge " + challenge);
            this.isChallenged = true;
            this.challengeResponseModel = challenge;
            this.authChallengeEvent.emit(challenge);
            this.currentEventHandler = this.eventHandler.challenge;
            console.log("handleChallenge, challenged is " + this.isChallenged);
        };
    }

performLogin(username: string, loginRequest: RequestModel<LoginRequestModel>) {
        console.log("come mfp.auth.service.ts performLogin");
        let performed = false;
        let authRequest = {
            requestHeader: {
                deviceId: this.sessionService.getDeviceId(),
                channelTime: new Date().toString()
            },
            requestBody: loginRequest.requestBody
        }
        this.processLoginGrantType = loginRequest.requestBody.grant_type;

        let authObj = {
            'authorization': environment.authorization,
            'authRequest': JSON.stringify(authRequest),
            'authCode': this.service.getHashMAC(authRequest, this.sessionService.getHashKey()),
            'authUser': username
        };
        console.log("mfp-performLogin|isChallenged1=" + this.isChallenged + "\nauthObj=\n" + JSON.stringify(authObj) + "\n\n");
        if (this.isChallenged) {
            console.log("mfp-performLogin|submitChallengeAnswer=");
            this.userLoginChallengeHandler.submitChallengeAnswer(authObj);
        } else {
            console.log("mfp-performLogin|WLAuthorizationManager.login=");
            WLAuthorizationManager.login(this.securityCheckName, authObj).then(
                () => {
                    console.log("mfp-performLogin|WLAuthorizationManager.login.performed=" + performed + "\nmfpAuthResponse=\n" + JSON.stringify(this.mfpAuthResponse) + "\n\n");
                    if (!performed) {
                        this.ngZone.run(() => {
                            console.log("come emit authSuccessEvent");
                            this.authSuccessEvent.emit(this.mfpAuthResponse);
                        });
                    }
                    performed = true;
                },
                (err) => {
                    console.log("mfp-performLogin|WLAuthorizationManager.login.err=\n\n" + JSON.stringify(err) + "\n");
                    console.log('wllogin err => ', err);
                    this.authFailureEvent.emit(err);
                }
            );
        }
    }

As you can see, from my login.component.ts, i will do ngOnInit() first, and after I key in password and press on login button, it will call the performLogin() method, and continue to call to mfp.auth.servicet.ts performLogin().

In mfp.auth.servicet.ts performLogin(), will call to WLAuthorizationManager.login(this.securityCheckName, authObj) because the this.isChallenged value is false by default.

The login is actually successful, as I able to get those oauth response and able to go into my application, my oauth response is something as follow:

enter image description here

The login is successful, but when I want to click to access to resource that having @OAuthSecurity, then my app will keep loading, and no error show in log. Something is blocking in mfp there.

If I remove the Scope-Element Mapping, and Mandatory Application Scope, then no issue, the request can go in successful.

Thus, I am suspecting something wrong in my configuration, or something wrong in my code logic. Really appreciate your advise and help. I am stuck in this more than 2 weeks.

As my understanding, there are 2 part of authentication on this, 1 is authentication with mfp, and another 1 is authentication with my backend service, which is the UserAuthentication.java, I believe my UserAuthentication.java already success authenticated, maybe something wrong with my authentication part with mfp?

And how can I know I have successful authenticate with mfp ya?

Base on this article, http://mobilefirstplatform.ibmcloud.com/tutorials/ru/foundation/8.0/authentication-and-security/credentials-validation/javascript/ And may I know when the handleChallenge() will be call? and also the handleSuccess().

Kindly let me know if need me to provide more information.

Panadol Chong
  • 1,793
  • 13
  • 54
  • 119
  • The token object in the query is a custom one, yes? Is this from the backend? If so, is this token sent along with the protected resource call as an Authorization header? – Vivin K Feb 09 '21 at 14:44
  • hi @VivinK, do u means accessToken: loginSuccess.user.attributes.access_token, ? Yes its from my backend, the value will be something like 767eb9ff-09f2-4559-81c0-5f6e642c16fc – Panadol Chong Feb 09 '21 at 15:00
  • handleChallenge() will be call? and also the ? --> handleChallenge() will be called when you are trying to access resource protected with UserAuthentication security check and success state for UserAuthentication security check has expired. You must answer the challenge to proceed further. handleSuccess() -- > success state for UserAuthentication security check is valid. handleFailure() --> If you exceeds the number of attempt to answer the challenge for ex: you submit wrong credentials more than number of attempt set in the adapter – manjunath kallannavar Feb 12 '21 at 09:16
  • And also I see you have added UserAuthentication as mandatory scope which means for every call you make to server you will be validated first on success state expiration of UserAuthentication security check, if valid --> allow to access resource else throw challenge ( handleChalleneg()) – manjunath kallannavar Feb 12 '21 at 09:19

0 Answers0