public async Task DiscoverEndpoints(IHttpClientFactory factory)
        {
            var httpClient = factory.CreateClient();
            var disco      = await httpClient.GetDiscoveryDocumentAsync(Issuer);

            if (!disco.IsError)
            {
                AccessTokenUrl = disco.TokenEndpoint;
                AuthorizeUrl   = disco.AuthorizeEndpoint;
                JwkSetUrl      = disco.JwksUri;
            }
            else if (AccessTokenUrl.IsPresent())
            {
                disco = await httpClient.GetDiscoveryDocumentAsync(AccessTokenUrl);

                if (!disco.IsError)
                {
                    AccessTokenUrl = disco.TokenEndpoint;
                    AuthorizeUrl   = disco.AuthorizeEndpoint;
                    JwkSetUrl      = disco.JwksUri;
                }
                else if (AuthorizeUrl.IsPresent())
                {
                    disco = await httpClient.GetDiscoveryDocumentAsync(AuthorizeUrl);

                    if (!disco.IsError)
                    {
                        AccessTokenUrl = disco.TokenEndpoint;
                        AuthorizeUrl   = disco.AuthorizeEndpoint;
                        JwkSetUrl      = disco.JwksUri;
                    }
                }
                else if (JwkSetUrl.IsPresent())
                {
                    disco = await httpClient.GetDiscoveryDocumentAsync(JwkSetUrl);

                    if (!disco.IsError)
                    {
                        AccessTokenUrl = disco.TokenEndpoint;
                        AuthorizeUrl   = disco.AuthorizeEndpoint;
                        JwkSetUrl      = disco.JwksUri;
                    }
                }
            }
        }
Example #2
0
        private IHttpResult RequestAccessToken(IServiceBase authService, IAuthSession session, string code, IAuthTokens tokens)
        {
            try
            {
                var formData = "client_id={0}&redirect_uri={1}&client_secret={2}&code={3}&grant_type=authorization_code&resource={4}"
                               .Fmt(ClientId.UrlEncode(), CallbackUrl.UrlEncode(), ClientSecret.UrlEncode(), code, ResourceId.UrlEncode());
                // Endpoint only accepts posts requests
                var contents = AccessTokenUrl.PostToUrl(formData);

                // 4. The Azure AD token issuance endpoint returns an access token
                //    and a refresh token. The refresh token can be used to request
                //    additional access tokens.

                // Response is JSON
                var authInfo    = JsonObject.Parse(contents);
                var authInfoNvc = authInfo.ToNameValueCollection();
                if (HasError(authInfoNvc))
                {
                    return(RedirectDueToFailure(authService, session, authInfoNvc));
                }
                tokens.AccessTokenSecret = authInfo["access_token"];
                tokens.RefreshToken      = authInfo["refresh_token"];
                return(OnAuthenticated(authService, session, tokens, authInfo.ToDictionary())
                       ?? authService.Redirect(SuccessRedirectUrlFilter(this, session.ReferrerUrl.SetParam("s", "1")))); //Haz Access!
            }
            catch (WebException webException)
            {
                if (webException.Response == null)
                {
                    // This could happen e.g. due to a timeout
                    return(RedirectDueToFailure(authService, session, new NameValueCollection
                    {
                        { "error", webException.GetType().ToString() },
                        { "error_description", webException.Message }
                    }));
                }
                Log.Error("Auth Failure", webException);
                var response     = ((HttpWebResponse)webException.Response);
                var responseText = Encoding.UTF8.GetString(
                    response.GetResponseStream().ReadFully());
                var errorInfo = JsonObject.Parse(responseText).ToNameValueCollection();
                return(RedirectDueToFailure(authService, session, errorInfo));
            }
            //return RedirectDueToFailure(authService, session, new NameValueCollection());
        }
Example #3
0
 private void ValidateClientAuthAccessRequestState()
 {
     if (AccessTokenUrl.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify an access token URL");
     }
     if (ConsumerKey.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify a consumer key");
     }
     if (ConsumerSecret.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify a consumer secret");
     }
     if (ClientUsername.IsNullOrBlank() || ClientPassword.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify user credentials");
     }
 }
Example #4
0
 private void ValidateAccessRequestState()
 {
     if (AccessTokenUrl.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify an access token URL");
     }
     if (ConsumerKey.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify a consumer key");
     }
     if (ConsumerSecret.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify a consumer secret");
     }
     if (Token.IsNullOrBlank())
     {
         throw new ArgumentException("You must specify a token");
     }
 }
        public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
        {
            IAuthTokens tokens      = Init(authService, ref session, request);
            IRequest    httpRequest = authService.Request;


            string error = httpRequest.QueryString["error"]
                           ?? httpRequest.QueryString["error_uri"]
                           ?? httpRequest.QueryString["error_description"];

            bool hasError = !error.IsNullOrEmpty();

            if (hasError)
            {
                Log.Error("Yandex error callback. {0}".Fmt(httpRequest.QueryString));
                return(authService.Redirect(FailedRedirectUrlFilter(this, session.ReferrerUrl.AddParam("f", error))));
            }

            string code = httpRequest.QueryString["code"];
            bool   isPreAuthCallback = !code.IsNullOrEmpty();

            if (!isPreAuthCallback)
            {
                string preAuthUrl = PreAuthUrl + "?response_type=code&client_id={0}&redirect_uri={1}&display=popup&state={2}".Fmt(ApplicationId, CallbackUrl.UrlEncode(), Guid.NewGuid().ToString("N"));

                authService.SaveSession(session, SessionExpiry);
                return(authService.Redirect(PreAuthUrlFilter(this, preAuthUrl)));
            }

            try
            {
                string payload  = "grant_type=authorization_code&code={0}&client_id={1}&client_secret={2}".Fmt(code, ApplicationId, ApplicationPassword);
                string contents = AccessTokenUrl.PostStringToUrl(payload);

                var authInfo = JsonObject.Parse(contents);

                //Yandex does not throw exception, but returns error property in JSON response
                // http://api.yandex.ru/oauth/doc/dg/reference/obtain-access-token.xml
                string accessTokenError = authInfo.Get("error");

                if (!accessTokenError.IsNullOrEmpty())
                {
                    Log.Error("Yandex access_token error callback. {0}".Fmt(authInfo.ToString()));
                    return(authService.Redirect(session.ReferrerUrl.AddParam("f", "AccessTokenFailed")));
                }
                tokens.AccessTokenSecret = authInfo.Get("access_token");

                session.IsAuthenticated = true;

                return(OnAuthenticated(authService, session, tokens, authInfo.ToDictionary())
                       ?? authService.Redirect(SuccessRedirectUrlFilter(this, session.ReferrerUrl.AddParam("s", "1"))));
            }
            catch (WebException webException)
            {
                //just in case Yandex will start throwing exceptions
                HttpStatusCode statusCode = ((HttpWebResponse)webException.Response).StatusCode;
                if (statusCode == HttpStatusCode.BadRequest)
                {
                    return(authService.Redirect(FailedRedirectUrlFilter(this, session.ReferrerUrl.AddParam("f", "AccessTokenFailed"))));
                }
            }
            return(authService.Redirect(FailedRedirectUrlFilter(this, session.ReferrerUrl.AddParam("f", "Unknown"))));
        }
Example #6
0
        public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
        {
            IAuthTokens tokens      = Init(authService, ref session, request);
            IRequest    httpRequest = authService.Request;


            string error = httpRequest.QueryString["error"];

            bool hasError = !error.IsNullOrEmpty();

            if (hasError)
            {
                Log.Error("Odnoklassniki error callback. {0}".Fmt(httpRequest.QueryString));
                return(authService.Redirect(session.ReferrerUrl));
            }

            string code = httpRequest.QueryString["code"];
            bool   isPreAuthCallback = !code.IsNullOrEmpty();

            if (!isPreAuthCallback)
            {
                string url = PreAuthUrl + "?client_id={0}&redirect_uri={1}&response_type=code&layout=m"
                             .Fmt(ApplicationId, CallbackUrl.UrlEncode());

                authService.SaveSession(session, SessionExpiry);
                return(authService.Redirect(url));
            }

            try
            {
                string payload = "client_id={0}&client_secret={1}&code={2}&redirect_uri={3}&grant_type=authorization_code"
                                 .Fmt(ApplicationId, SecretKey, code, CallbackUrl.UrlEncode());

                string contents = AccessTokenUrl.PostToUrl(payload, "*/*", RequestFilter);

                var authInfo = JsonObject.Parse(contents);

                //ok.ru does not throw exception, but returns error property in JSON response
                string accessTokenError = authInfo.Get("error");

                if (!accessTokenError.IsNullOrEmpty())
                {
                    Log.Error("Odnoklassniki access_token error callback. {0}".Fmt(authInfo.ToString()));
                    return(authService.Redirect(session.ReferrerUrl.AddParam("f", "AccessTokenFailed")));
                }
                tokens.AccessTokenSecret = authInfo.Get("access_token");
                tokens.UserId            = authInfo.Get("user_id");

                session.IsAuthenticated = true;

                return(OnAuthenticated(authService, session, tokens, authInfo.ToDictionary())
                       ?? authService.Redirect(session.ReferrerUrl.AddParam("s", "1")));
            }
            catch (WebException webException)
            {
                //just in case it starts throwing exceptions
                HttpStatusCode statusCode = ((HttpWebResponse)webException.Response).StatusCode;
                if (statusCode == HttpStatusCode.BadRequest)
                {
                    return(authService.Redirect(session.ReferrerUrl.AddParam("f", "AccessTokenFailed")));
                }
            }
            return(authService.Redirect(session.ReferrerUrl.AddParam("f", "Unknown")));
        }
        public override async Task <object> AuthenticateAsync(IServiceBase authService, IAuthSession session, Authenticate request, CancellationToken token = default)
        {
            IAuthTokens tokens      = Init(authService, ref session, request);
            var         ctx         = CreateAuthContext(authService, session, tokens);
            IRequest    httpRequest = authService.Request;

            string error = httpRequest.QueryString["error"]
                           ?? httpRequest.QueryString["error_uri"]
                           ?? httpRequest.QueryString["error_description"];

            bool hasError = !error.IsNullOrEmpty();

            if (hasError)
            {
                Log.Error($"Yandex error callback. {httpRequest.QueryString}");
                return(authService.Redirect(FailedRedirectUrlFilter(ctx, session.ReferrerUrl.SetParam("f", error))));
            }

            string code = httpRequest.QueryString["code"];
            bool   isPreAuthCallback = !code.IsNullOrEmpty();

            if (!isPreAuthCallback)
            {
                string preAuthUrl = $"{PreAuthUrl}?response_type=code&client_id={ApplicationId}&redirect_uri={CallbackUrl.UrlEncode()}&display=popup&state={Guid.NewGuid().ToString("N")}";
                await this.SaveSessionAsync(authService, session, SessionExpiry, token).ConfigAwait();

                return(authService.Redirect(PreAuthUrlFilter(ctx, preAuthUrl)));
            }

            try
            {
                string payload  = $"grant_type=authorization_code&code={code}&client_id={ApplicationId}&client_secret={ApplicationPassword}";
                string contents = await AccessTokenUrl.PostStringToUrlAsync(payload).ConfigAwait();

                var authInfo = JsonObject.Parse(contents);

                //Yandex does not throw exception, but returns error property in JSON response
                // http://api.yandex.ru/oauth/doc/dg/reference/obtain-access-token.xml
                string accessTokenError = authInfo.Get("error");

                if (!accessTokenError.IsNullOrEmpty())
                {
                    Log.Error($"Yandex access_token error callback. {authInfo}");
                    return(authService.Redirect(session.ReferrerUrl.SetParam("f", "AccessTokenFailed")));
                }
                tokens.AccessTokenSecret = authInfo.Get("access_token");

                session.IsAuthenticated = true;

                return(await OnAuthenticatedAsync(authService, session, tokens, authInfo.ToDictionary(), token).ConfigAwait()
                       ?? await authService.Redirect(SuccessRedirectUrlFilter(ctx, session.ReferrerUrl.SetParam("s", "1"))).SuccessAuthResultAsync(authService, session).ConfigAwait());
            }
            catch (WebException webException)
            {
                //just in case Yandex will start throwing exceptions
                var statusCode = ((HttpWebResponse)webException.Response).StatusCode;
                if (statusCode == HttpStatusCode.BadRequest)
                {
                    return(authService.Redirect(FailedRedirectUrlFilter(ctx, session.ReferrerUrl.SetParam("f", "AccessTokenFailed"))));
                }
            }
            return(authService.Redirect(FailedRedirectUrlFilter(ctx, session.ReferrerUrl.SetParam("f", "Unknown"))));
        }