public void LoginCallback(Principal client, string idTokenResponseStr, Google_IdP idp)
            {
                var authorizationCodeResponse = JsonConvert.DeserializeObject <AuthorizationCodeResponse>(idTokenResponseStr);

                authorizationCodeResponseStructure.Import(authorizationCodeResponse,
                                                          // We don't know who produced the redirection.
                                                          Channel.GenerateNew(SVX_Principal),
                                                          client);

                var validationRequest = SVX_Ops.Call(SVX_MakeValidationRequest, authorizationCodeResponse);

                validationRequestStructure.Export(validationRequest, googlePrincipal, null);
                var validationRequestStr = JsonConvert.SerializeObject(validationRequest);

                var validationResponseStr = idp.ValidationEndpoint(validationRequestStr);

                var validationResponse = JsonConvert.DeserializeObject <ValidationResponse>(validationResponseStr);

                validationResponseStructure.ImportDirectResponse(validationResponse, googlePrincipal, SVX_Principal);

                // SVX will automatically detect using message IDs that
                // validationResponse actually resulted from
                // authorizationCodeResponse and not merely another message with
                // the same SymT.  This is essential for us to establish the
                // relationship between authorizationCodeResponse.SVX_sender and
                // validationResponse.googleUsername.
                var conc = SVX_Ops.Call(SVX_SignInRP, authorizationCodeResponse, validationResponse);

                SVX_Ops.Certify(conc, LoginSafety);
                SVX_Ops.Certify(conc, LoginXSRFPrevention, new ParticipantId(googlePrincipal, typeof(Google_IdP)));
                // AbandonAndCreateSession...
            }