Exemplo n.º 1
0
        public async Task <GoodIdResponse> CollectAsync()
        {
            var sessionDataHandler = mServiceLocator.SessionDataHandler;
            var stateNonceHandler  = mServiceLocator.StateNonceHandler;

            try
            {
                var goodIdServerConfig = mServiceLocator.ServerConfig;
                var requestFactory     = mServiceLocator.RequestFactory;

                var method = mIncomingRequest.GetMethod();

                // Check HTTP method - Only HTTP GET acceptable when OP retun to the RP
                if (method != IncomingRequest.Method.GET)
                {
                    throw new GoodIdException($"Unexpected request method {method}!");
                }

                if (!stateNonceHandler.ValidateState(mIncomingRequest.GetStringParameter("state")))
                {
                    throw new ValidationException("The received state is invalid.");
                }

                var authCode = mIncomingRequest.GetStringParameter("code");

                // Handle error case
                if (string.IsNullOrEmpty(authCode))
                {
                    var error = mIncomingRequest.GetStringParameter("error");

                    if (string.IsNullOrEmpty(error))
                    {
                        throw new GoodIdException("Neither code nor error parameter is set.");
                    }

                    var errorDescription = mIncomingRequest.GetStringParameter("error_description");

                    return(new GoodIdResponseError(error, errorDescription));
                }

                // Session parameters
                var requestSourceJson = sessionDataHandler.GetVariableRawJson(SessionDataHandler.SESSION_KEY_REQUEST_SOURCE);
                var usedRedirectUri   = sessionDataHandler.GetVariableString(SessionDataHandler.SESSION_KEY_USED_REDIRECT_URI);

                if (string.IsNullOrEmpty(requestSourceJson))
                {
                    throw new GoodIdException("Request source is not set in session!");
                }

                if (string.IsNullOrEmpty(usedRedirectUri))
                {
                    throw new GoodIdException("Redirect uri is not set in session!");
                }


                var tokenResponse = await requestFactory.CreateTokenRequest(
                    goodIdServerConfig,
                    mServiceLocator.Logger,
                    mClientId,
                    mClientSecret,
                    usedRedirectUri,
                    authCode,
                    null
                    ).ExecuteAsync();

                var jwe = tokenResponse.IdTokenJwe;

                var requestJObject = await GetRequestJObjectAsync(requestSourceJson, mSigningKey);

                int?requestedMaxAge = requestJObject?["max_age"] != null
                    ? (int?)requestJObject["max_age"]
                    : null;

                var authTimeRequested = false;

                if (requestJObject["claims"] != null && requestJObject["claims"]["id_token"] != null && requestJObject["claims"]["id_token"]["auth_time"] != null && requestJObject["claims"]["id_token"]["auth_time"]["essential"] != null)
                {
                    authTimeRequested |= (requestJObject["claims"]["id_token"]["auth_time"]["essential"].ToObject <bool>()) == true;
                }
                if (requestJObject["claims"] != null && requestJObject["claims"]["userinfo"] != null && requestJObject["claims"]["userinfo"]["auth_time"] != null && requestJObject["claims"]["userinfo"]["auth_time"]["essential"] != null)
                {
                    authTimeRequested |= (requestJObject["claims"]["userinfo"]["auth_time"]["essential"].ToObject <bool>()) == true;
                }

                TokenExtractor tokenExtractor = mServiceLocator.GetTokenExtractor(mEncryptionKeys);
                JObject        idToken        = tokenExtractor.ExtractToken(jwe);

                var idTokenVerifier = mServiceLocator.getIdTokenVerifier(
                    idToken,
                    mClientId,
                    requestedMaxAge,
                    authTimeRequested,
                    stateNonceHandler.getCurrentNonce());
                idTokenVerifier.Verify();

                if (tokenResponse.AccessToken != null)
                {
                    var accessToken = tokenResponse.AccessToken;

                    var userinfoResponse = await requestFactory.CreateUserinfoRequest(
                        goodIdServerConfig,
                        accessToken
                        ).ExecuteAsync();

                    JObject userinfo = tokenExtractor.ExtractToken(userinfoResponse.UserinfoJwe);

                    var userinfoVerifier = mServiceLocator.GetUserinfoVerifier(idToken, userinfo);
                    userinfoVerifier.Verify();

                    //TODO: matching validation
                    var validator = mServiceLocator.ResponseValidator;
                    validator.ValidateTokensBelongTogether(idToken, userinfo);
                    if (mMatchingResponseValidation)
                    {
                        if (requestJObject != null && requestJObject["claims"] != null && requestJObject["claims"].Type == JTokenType.Object)
                        {
                            validator.ValidateMatchingResponse((JObject)requestJObject["claims"], userinfo);
                        }
                        else
                        {
                            throw new ValidationException("Matching response validation cannot succeed because the request object was probably encrypted, or nothing was requested.");
                        }
                    }

                    var combined = MergeTokens(idToken, userinfo);

                    return(new GoodIdResponseSuccess(accessToken, combined));
                }
                else
                {
                    throw new GoodIdException("You don't have access token.");
                }
            }
            catch (GoodIdException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new GoodIdException("Unknown error: " + e);
            }
            finally
            {
                sessionDataHandler.RemoveAllGoodIdVariables();
            }
        }