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...
            }
        public static void Test()
        {
            var idp = new Google_IdP(googlePrincipal);
            var rp  = new FooMerchant_RP(Entity.Of("FooMerchant"));

            var aliceIdP = Channel.GenerateNew(googlePrincipal);
            var aliceRP  = Channel.GenerateNew(rp.SVX_Principal);

            var codeRequestStr  = rp.LoginStart(aliceRP);
            var codeResponseStr = idp.CodeEndpoint(aliceIdP, codeRequestStr);

            rp.LoginCallback(aliceRP, codeResponseStr, idp);  // Includes the validation server-to-server call
        }
        public static void Test()
        {
            var idp = new Google_IdP(googlePrincipal);
            var rp  = new FooMerchant_RP(Entity.Of("FooMerchant"));

            var aliceIdP = Channel.GenerateNew(googlePrincipal);
            var aliceRP  = Channel.GenerateNew(rp.SVX_Principal);

            var idTokenRequestStr  = rp.LoginStart(aliceRP);
            var idTokenResponseStr = idp.TokenEndpoint(aliceIdP, idTokenRequestStr);

            rp.LoginCallback(aliceRP, idTokenResponseStr);
        }