/// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application doesn’t already 
        /// exist for the user; otherwise, returns the user’s existing authorization for that application.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client ID of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task<ApplicationAuthorization> GetOrCreateApplicationAuthentication(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");

            var requestData = new
            {
                client_secret = clientSecret,
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl
            };

            if (String.IsNullOrWhiteSpace(newAuthorization.Fingerprint))
            {
                // use classic API
                var endpoint = ApiUrls.AuthorizationsForClient(clientId);
                return ApiConnection.Put<ApplicationAuthorization>(endpoint, requestData);
            }
            else
            {
                // use new API
                var endpoint = ApiUrls.AuthorizationsForClient(clientId, newAuthorization.Fingerprint);
                return ApiConnection.Put<ApplicationAuthorization>(endpoint, requestData, null, previewAcceptsHeader);
            }
        }
Example #2
0
        public IObservable<ApplicationAuthorization> GetOrCreateApplicationAuthenticationCode(
            Func<TwoFactorAuthorizationException, IObservable<TwoFactorChallengeResult>> twoFactorChallengeHander,
            string authenticationCode = null,
            bool useOldScopes = false,
            bool useFingerPrint = true)
        {
            var newAuthorization = new NewAuthorization
            {
                Scopes = useOldScopes
                    ? oldAuthorizationScopes
                    : newAuthorizationScopes,
                Note = lazyNote.Value,
                Fingerprint = useFingerPrint ? lazyFingerprint.Value : null
            };

            Func<TwoFactorAuthorizationException, IObservable<TwoFactorChallengeResult>> dispatchedHandler =
                ex => Observable.Start(() => twoFactorChallengeHander(ex), RxApp.MainThreadScheduler).Merge();

            var authorizationsClient = gitHubClient.Authorization;

            return string.IsNullOrEmpty(authenticationCode)
                ? authorizationsClient.CreateAndDeleteExistingApplicationAuthorization(
                        ClientId,
                        ClientSecret,
                        newAuthorization,
                        dispatchedHandler,
                        true)
                :   authorizationsClient.CreateAndDeleteExistingApplicationAuthorization(
                        ClientId,
                        ClientSecret,
                        newAuthorization,
                        dispatchedHandler,
                        authenticationCode,
                        true);
        }
        /// <summary>
        /// This method will create a new authorization for the specified OAuth application, only if an authorization 
        /// for that application doesn’t already exist for the user. It returns the user’s token for the application
        /// if one exists. Otherwise, it creates a new one.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method allows the caller to provide a callback which is used to retrieve the two-factor code from
        /// the user. Typically the callback is used to show some user interface to the user.
        /// </para>
        /// <para>
        /// See <a href="http://developer.github.com/v3/oauth/#list-your-authorizations">API documentation</a> 
        /// for more details.
        /// </para>
        /// </remarks>
        /// <param name="authorizationsClient">The <see cref="IAuthorizationsClient" /> this method extends</param>
        /// <param name="clientId">Client ID for the OAuth application that is requesting the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Defines the scopes and metadata for the token</param>
        /// <param name="twoFactorChallengeHandler">Callback used to retrieve the two-factor authentication code
        /// from the user</param>
        /// <returns></returns>
        public static async Task<Authorization> GetOrCreateApplicationAuthentication(
            this IAuthorizationsClient authorizationsClient,
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization,
            Func<TwoFactorRequiredException, Task<TwoFactorChallengeResult>> twoFactorChallengeHandler
            )
        {
            TwoFactorRequiredException twoFactorException = null;
            try
            {
                return await authorizationsClient.GetOrCreateApplicationAuthentication(clientId, clientSecret, newAuthorization)
                                                 .ConfigureAwait(false);
            }
            catch (TwoFactorRequiredException exception)
            {
                twoFactorException = exception;
            }
            var twoFactorChallengeResult = await twoFactorChallengeHandler(twoFactorException).ConfigureAwait(false);

            return await (twoFactorChallengeResult.ResendCodeRequested
                ? authorizationsClient.GetOrCreateApplicationAuthentication(
                    clientId,
                    clientSecret,
                    newAuthorization,
                    twoFactorChallengeHandler).ConfigureAwait(false)
                : authorizationsClient.GetOrCreateApplicationAuthentication(
                    clientId,
                    clientSecret,
                    newAuthorization,
                    twoFactorChallengeResult.AuthenticationCode).ConfigureAwait(false));
        }
        /// <summary>
        /// This method will create a new authorization for the specified OAuth application, only if an authorization 
        /// for that application doesn’t already exist for the user. It returns the user’s token for the application
        /// if one exists. Otherwise, it creates a new one.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method allows the caller to provide a callback which is used to retrieve the two-factor code from
        /// the user. Typically the callback is used to show some user interface to the user.
        /// </para>
        /// <para>
        /// See <a href="http://developer.github.com/v3/oauth/#list-your-authorizations">API documentation</a> 
        /// for more details.
        /// </para>
        /// </remarks>
        /// <param name="authorizationsClient">The <see cref="IAuthorizationsClient" /> this method extends</param>
        /// <param name="clientId">Client ID for the OAuth application that is requesting the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Defines the scopes and metadata for the token</param>
        /// <param name="twoFactorChallengeHandler">Callback used to retrieve the two-factor authentication code
        /// from the user</param>
        /// <returns></returns>
        public static IObservable<ApplicationAuthorization> GetOrCreateApplicationAuthentication(
            this IObservableAuthorizationsClient authorizationsClient,
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization,
            Func<TwoFactorRequiredException, IObservable<TwoFactorChallengeResult>> twoFactorChallengeHandler)
        {
            Ensure.ArgumentNotNull(authorizationsClient, "authorizationsClient");
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");

            return authorizationsClient.GetOrCreateApplicationAuthentication(clientId, clientSecret, newAuthorization)
                .Catch<ApplicationAuthorization, TwoFactorRequiredException>(exception => twoFactorChallengeHandler(exception)
                    .SelectMany(result =>
                        result.ResendCodeRequested
                            ? authorizationsClient.GetOrCreateApplicationAuthentication(
                                clientId,
                                clientSecret,
                                newAuthorization,
                                twoFactorChallengeHandler)
                            : authorizationsClient.GetOrCreateApplicationAuthentication(clientId,
                                clientSecret,
                                newAuthorization,
                                result.AuthenticationCode)));
        }
        /// <summary>
        /// Creates a new personal token for the authenticated user.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization">API documentation</a> for more information.
        /// </remarks>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task<ApplicationAuthorization> Create(NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNull(newAuthorization, "authorization");

            var requestData = new
            {
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl,
                fingerprint = newAuthorization.Fingerprint
            };

            var endpoint = ApiUrls.Authorizations();

            return ApiConnection.Post<ApplicationAuthorization>(endpoint, requestData);
        }
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application doesn’t already 
        /// exist for the user; otherwise, returns the user’s existing authorization for that application.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client ID of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task<Authorization> GetOrCreateApplicationAuthentication(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");

            var endpoint = "authorizations/clients/{0}".FormatUri(clientId);
            var requestData = new
            {
                client_secret = clientSecret,
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl
            };

            return ApiConnection.Put<Authorization>(endpoint, requestData);
        }
Example #7
0
 // If the Application Authorization already exists, the result might have an empty string as the token. This is
 // because GitHub.com no longer stores the token, but stores a hashed version of it. It is assumed that clients
 // will store the token locally.
 // The only reason to be calling GetOrCreateApplicationAuthentication is pretty much the case when you are
 // logging in and thus don't have the token already. So if the token returned is an empty string, we'll go
 // ahead and delete it for you and then recreate it.
 static IObservable <ApplicationAuthorization> CreateAuthorizationAndDeleteExisting(
     this IObservableAuthorizationsClient authorizationsClient,
     string clientId,
     string clientSecret,
     NewAuthorization newAuthorization,
     string twoFactorAuthenticationCode = null)
 {
     return(authorizationsClient.GetOrCreateAuthorizationUnified(
                clientId,
                clientSecret,
                newAuthorization,
                twoFactorAuthenticationCode)
            .SelectMany(authorization => string.IsNullOrEmpty(authorization.Token)
             ? authorizationsClient.Delete(authorization.Id, twoFactorAuthenticationCode)
                        .SelectMany(_ =>
                                    authorizationsClient.CreateNewAuthorization(
                                        clientId,
                                        clientSecret,
                                        newAuthorization,
                                        twoFactorAuthenticationCode))
             : Observable.Return(authorization)));
 }
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application doesn’t already
        /// exist for the user; otherwise, returns the user’s existing authorization for that application.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client ID of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task <ApplicationAuthorization> GetOrCreateApplicationAuthentication(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");

            var requestData = new
            {
                client_secret = clientSecret,
                scopes        = newAuthorization.Scopes,
                note          = newAuthorization.Note,
                note_url      = newAuthorization.NoteUrl,
                fingerprint   = newAuthorization.Fingerprint
            };

            var endpoint = ApiUrls.AuthorizationsForClient(clientId);

            return(ApiConnection.Put <ApplicationAuthorization>(endpoint, requestData));
        }
Example #9
0
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application
        /// doesn’t already exist for the user; otherwise, it fails.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client Id of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task <ApplicationAuthorization> Create(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, nameof(clientId));
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, nameof(clientSecret));
            Ensure.ArgumentNotNull(newAuthorization, nameof(newAuthorization));

            var requestData = new
            {
                client_id     = clientId,
                client_secret = clientSecret,
                scopes        = newAuthorization.Scopes,
                note          = newAuthorization.Note,
                note_url      = newAuthorization.NoteUrl,
                fingerprint   = newAuthorization.Fingerprint
            };

            var endpoint = ApiUrls.Authorizations();

            return(ApiConnection.Post <ApplicationAuthorization>(endpoint, requestData));
        }
Example #10
0
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application
        /// doesn’t already exist for the user; otherwise, it fails.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client ID of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task<ApplicationAuthorization> Create(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");

            var requestData = new
            {
                client_id = clientId,
                client_secret = clientSecret,
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl,
                fingerprint = newAuthorization.Fingerprint
            };

            var endpoint = ApiUrls.Authorizations();

            return ApiConnection.Post<ApplicationAuthorization>(endpoint, requestData);
        }
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application doesn’t already 
        /// exist for the user; otherwise, returns the user’s existing authorization for that application.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client ID of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <param name="twoFactorAuthenticationCode">The two-factor authentication code in response to the current user's previous challenge</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public async Task<ApplicationAuthorization> GetOrCreateApplicationAuthentication(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization,
            string twoFactorAuthenticationCode)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");
            Ensure.ArgumentNotNullOrEmptyString(twoFactorAuthenticationCode, "twoFactorAuthenticationCode");

            var requestData = new
            {
                client_secret = clientSecret,
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl
            };

            try
            {
                if (String.IsNullOrWhiteSpace(newAuthorization.Fingerprint))
                {
                    // use classic API
                    var endpoint = ApiUrls.AuthorizationsForClient(clientId);
                    return await ApiConnection.Put<ApplicationAuthorization>(
                        endpoint,
                        requestData,
                        twoFactorAuthenticationCode);
                }
                else
                {
                    // use new API
                    var endpoint = ApiUrls.AuthorizationsForClient(clientId, newAuthorization.Fingerprint);
                    return await ApiConnection.Put<ApplicationAuthorization>(
                        endpoint,
                        requestData,
                        twoFactorAuthenticationCode,
                        previewAcceptsHeader);
                }
            }
            catch (AuthorizationException e)
            {
                throw new TwoFactorChallengeFailedException(e);
            }
        }
        private async Task LoginWithUsernameAndPassword([NotNull] Credentials credentials)
        {
            _log.Write(LogLevel.Debug, "Logging in with credentials");
            _github.Credentials = credentials;

            try
            {
                SettingsCache.SaveCredentials(credentials.Login, credentials.Password);
                var newAuth = new NewAuthorization
                {
                    Scopes = new[] { "user", "repo" },
                    Note = "GitHub Visual Studio Extension",
                    NoteUrl = "http://www.alteridem.net",
                    Fingerprint = AuthenticationHelpers.GetFingerprint()
                };

                var auth = await _github.Authorization.GetOrCreateApplicationAuthentication( Secrets.CLIENT_ID, Secrets.CLIENT_SECRET, newAuth );
                _log.Write( LogLevel.Info, "Successfully logged in to GitHub" );
                Token = auth.HashedToken;

                await LoadData();
            }
            catch (Exception ex)
            {
                _log.Write(LogLevel.Warn, "Failed to login", ex);
                Logout();
                throw;
            }
        }
Example #13
0
        private static Config Setup()
        {
            var config = new Config();
            Console.WriteLine("Lpgist Setup");

            Console.Write("lprun.exe path [lprun.exe]: ");
            var lprun = Console.ReadLine();
            if (!string.IsNullOrWhiteSpace(lprun))
                config.LprunPath = lprun.Trim(' ', '"', '\'');

            Console.Write("Default format(text|html|htmlfrag|csv|csvi) [html]: ");
            var format = Console.ReadLine();
            if (!string.IsNullOrWhiteSpace(format))
                config.Format = format.Trim();

            Console.Write("Want to log into GitHub? [yes]: ");
            if (YesOrNo(true))
            {
                Console.Write("Username: "******"Password: "******"1c6ea6235caf92bd0f0e";
                const string clientSecret = "fd0924a473072503af961a3214a9933e96b930d2";

                var newAuthorization = new NewAuthorization(
                    "Lpgist requires Gist access to upload your queries.",
                    new[] { "gist" });

                ApplicationAuthorization result;
                try
                {
                    result = client.Authorization
                        .Create(clientId, clientSecret, newAuthorization)
                        .GetAwaiter().GetResult();
                }
                catch (TwoFactorRequiredException ex)
                {
                    Console.Write("Two-factor code from {0}: ", ex.TwoFactorType);
                    var code = Console.ReadLine()?.Trim();
                    result = client.Authorization
                        .Create(clientId, clientSecret, newAuthorization, code)
                        .GetAwaiter().GetResult();
                }

                config.GitHubAccessToken = result.Token;

                Console.Write("Want the gists to be public? [yes]: ");
                config.IsPublic = YesOrNo(true);
            }

            Console.WriteLine();

            return config;
        }
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application doesn’t already 
        /// exist for the user; otherwise, returns the user’s existing authorization for that application.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client ID of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task<ApplicationAuthorization> GetOrCreateApplicationAuthentication(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");

            var requestData = new
            {
                client_secret = clientSecret,
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl
            };

            var endpoint = string.IsNullOrWhiteSpace(newAuthorization.Fingerprint)
                ? ApiUrls.AuthorizationsForClient(clientId)
                : ApiUrls.AuthorizationsForClient(clientId, newAuthorization.Fingerprint);

            return ApiConnection.Put<ApplicationAuthorization>(endpoint, requestData);
        }
        /// <summary>
        /// Creates a new <see cref="Authorization"/>.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#create-a-new-authorization">API documentation</a> for more information.
        /// </remarks>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make the request.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task <Authorization> Create(NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNull(newAuthorization, "newAuthorization");

            return(ApiConnection.Post <Authorization>(ApiUrls.Authorizations(), newAuthorization));
        }
 // If the Application Authorization already exists, the result might have an empty string as the token. This is
 // because GitHub.com no longer stores the token, but stores a hashed version of it. It is assumed that clients
 // will store the token locally.
 // The only reason to be calling GetOrCreateApplicationAuthentication is pretty much the case when you are
 // logging in and thus don't have the token already. So if the token returned is an empty string, we'll go
 // ahead and delete it for you and then recreate it.
 static IObservable<ApplicationAuthorization> CreateAuthorizationAndDeleteExisting(
     this IObservableAuthorizationsClient authorizationsClient,
     string clientId,
     string clientSecret,
     NewAuthorization newAuthorization,
     string twoFactorAuthenticationCode = null)
 {
     return authorizationsClient.GetOrCreateAuthorizationUnified(
         clientId,
         clientSecret,
         newAuthorization,
         twoFactorAuthenticationCode)
         .SelectMany(authorization => string.IsNullOrEmpty(authorization.Token)
             ? authorizationsClient.Delete(authorization.Id, twoFactorAuthenticationCode)
                 .SelectMany(_ =>
                     authorizationsClient.CreateNewAuthorization(
                         clientId,
                         clientSecret,
                         newAuthorization,
                         twoFactorAuthenticationCode))
             : Observable.Return(authorization));
 }
        /// <summary>
        /// Creates a new <see cref="Authorization"/>.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#create-a-new-authorization">API documentation</a> for more information.
        /// </remarks>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make the request.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task<Authorization> Create(NewAuthorization newAuthorization)
        {
            Ensure.ArgumentNotNull(newAuthorization, "newAuthorization");

            return ApiConnection.Post<Authorization>(ApiUrls.Authorizations(), newAuthorization);
        }
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application doesn’t already 
        /// exist for the user; otherwise, returns the user’s existing authorization for that application.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client ID of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <param name="twoFactorAuthenticationCode">The two-factor authentication code in response to the current user's previous challenge</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public async Task<Authorization> GetOrCreateApplicationAuthentication(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization,
            string twoFactorAuthenticationCode)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "authorization");
            Ensure.ArgumentNotNullOrEmptyString(twoFactorAuthenticationCode, "twoFactorAuthenticationCode");

            var endpoint = "authorizations/clients/{0}".FormatUri(clientId);
            var requestData = new
            {
                client_secret = clientSecret,
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl
            };

            try
            {
                return await ApiConnection.Put<Authorization>(
                    endpoint,
                    requestData,
                    twoFactorAuthenticationCode);
            }
            catch (AuthorizationException e)
            {
                throw new TwoFactorChallengeFailedException(e);
            }
        }
 static IObservable<ApplicationAuthorization> CreateNewAuthorization(
     this IObservableAuthorizationsClient authorizationsClient,
     string clientId,
     string clientSecret,
     NewAuthorization newAuthorization,
     string twoFactorAuthenticationCode = null)
 {
     return string.IsNullOrEmpty(twoFactorAuthenticationCode)
         ? authorizationsClient.Create(clientId, clientSecret, newAuthorization)
         : authorizationsClient.Create(clientId, clientSecret, newAuthorization, twoFactorAuthenticationCode);
 }
        /// <summary>
        /// Creates a new personal token for the authenticated user.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization">API documentation</a> for more information.
        /// </remarks>
        /// <param name="twoFactorAuthenticationCode">The two-factor authentication code in response to the current user's previous challenge</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public Task<ApplicationAuthorization> Create(
            NewAuthorization newAuthorization,
            string twoFactorAuthenticationCode)
        {
            Ensure.ArgumentNotNull(newAuthorization, "authorization");
            Ensure.ArgumentNotNullOrEmptyString(twoFactorAuthenticationCode, "twoFactorAuthenticationCode");

            var requestData = new
            {
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl,
                fingerprint = newAuthorization.Fingerprint
            };

            var endpoint = ApiUrls.Authorizations();
            return ApiConnection.Post<ApplicationAuthorization>(endpoint, requestData, null, null, twoFactorAuthenticationCode);
        }
        /// <summary>
        /// Creates a new authorization for the specified OAuth application if an authorization for that application doesn’t already 
        /// exist for the user; otherwise, returns the user’s existing authorization for that application.
        /// </summary>
        /// <remarks>
        /// This method requires authentication.
        /// See the <a href="http://developer.github.com/v3/oauth/#get-or-create-an-authorization-for-a-specific-app">API documentation</a> for more information.
        /// </remarks>
        /// <param name="clientId">Client Id of the OAuth application for the token</param>
        /// <param name="clientSecret">The client secret</param>
        /// <param name="newAuthorization">Describes the new authorization to create</param>
        /// <param name="twoFactorAuthenticationCode">The two-factor authentication code in response to the current user's previous challenge</param>
        /// <exception cref="AuthorizationException">
        /// Thrown when the current user does not have permission to make this request.
        /// </exception>
        /// <exception cref="TwoFactorRequiredException">
        /// Thrown when the current account has two-factor authentication enabled and an authentication code is required.
        /// </exception>
        /// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
        /// <returns>The created <see cref="Authorization"/>.</returns>
        public async Task<ApplicationAuthorization> GetOrCreateApplicationAuthentication(
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization,
            string twoFactorAuthenticationCode)
        {
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "newAuthorization");
            Ensure.ArgumentNotNullOrEmptyString(twoFactorAuthenticationCode, "twoFactorAuthenticationCode");

            var requestData = new
            {
                client_secret = clientSecret,
                scopes = newAuthorization.Scopes,
                note = newAuthorization.Note,
                note_url = newAuthorization.NoteUrl,
                fingerprint = newAuthorization.Fingerprint
            };

            try
            {
                var endpoint = ApiUrls.AuthorizationsForClient(clientId);

                return await ApiConnection.Put<ApplicationAuthorization>(endpoint, requestData, twoFactorAuthenticationCode).ConfigureAwait(false);
            }
            catch (AuthorizationException e)
            {
                throw new TwoFactorChallengeFailedException(twoFactorAuthenticationCode, e);
            }
        }
        public static IObservable<ApplicationAuthorization> CreateAndDeleteExistingApplicationAuthorization(
            this IObservableAuthorizationsClient authorizationsClient,
            string clientId,
            string clientSecret,
            NewAuthorization newAuthorization,
            Func<TwoFactorAuthorizationException, IObservable<TwoFactorChallengeResult>> twoFactorChallengeHandler,
            string twoFactorAuthenticationCode,
            bool retryInvalidTwoFactorCode)
        {
            Ensure.ArgumentNotNull(authorizationsClient, "authorizationsClient");
            Ensure.ArgumentNotNullOrEmptyString(clientId, "clientId");
            Ensure.ArgumentNotNullOrEmptyString(clientSecret, "clientSecret");
            Ensure.ArgumentNotNull(newAuthorization, "newAuthorization");

            // If retryInvalidTwoFactorCode is false, then we only show the TwoFactorDialog when we catch 
            // a TwoFactorRequiredException. If it's true, we show it for TwoFactorRequiredException and 
            // TwoFactorChallengeFailedException
            Func<TwoFactorAuthorizationException, IObservable<TwoFactorChallengeResult>> twoFactorHandler = ex =>
                retryInvalidTwoFactorCode || ex is TwoFactorRequiredException
                    ? twoFactorChallengeHandler(ex)
                    : Observable.Throw<TwoFactorChallengeResult>(ex);

            return authorizationsClient.CreateAuthorizationAndDeleteExisting(
                clientId,
                clientSecret,
                newAuthorization,
                twoFactorAuthenticationCode)
                .Catch<ApplicationAuthorization, TwoFactorAuthorizationException>(
                    exception => twoFactorHandler(exception)
                    .SelectMany(result =>
                        result.ResendCodeRequested
                            ? authorizationsClient.CreateAndDeleteExistingApplicationAuthorization(
                                clientId,
                                clientSecret,
                                newAuthorization,
                                twoFactorHandler,
                                null, // twoFactorAuthenticationCode
                                retryInvalidTwoFactorCode)
                            : authorizationsClient.CreateAndDeleteExistingApplicationAuthorization(
                                    clientId,
                                    clientSecret,
                                    newAuthorization,
                                    twoFactorHandler,
                                    result.AuthenticationCode,
                                    retryInvalidTwoFactorCode)));
        }
 /// <summary>
 /// This method will create a new authorization for the specified OAuth application. If an authorization 
 /// for that application already exists for the user and fingerprint, it'll delete the existing one and 
 /// recreate it.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This method is typically used to initiate an application authentication flow.
 /// This method allows the caller to provide a callback which is used to retrieve the two-factor code from
 /// the user. Typically the callback is used to show some user interface to the user.
 /// </para>
 /// <para>
 /// See <a href="http://developer.github.com/v3/oauth/#list-your-authorizations">API documentation</a> 
 /// for more details.
 /// </para>
 /// </remarks>
 /// <param name="authorizationsClient">The <see cref="IAuthorizationsClient" /> this method extends</param>
 /// <param name="clientId">Client ID for the OAuth application that is requesting the token</param>
 /// <param name="clientSecret">The client secret</param>
 /// <param name="newAuthorization">Defines the scopes and metadata for the token</param>
 /// <param name="twoFactorChallengeHandler">Callback used to retrieve the two-factor authentication code
 /// from the user</param>
 /// <param name="retryInvalidTwoFactorCode">If true, instead of completing when the two factor code supplied
 /// is invalid, we go through the whole cycle again and prompt the two factor dialog.</param>
 /// <returns></returns>
 public static IObservable<ApplicationAuthorization> CreateAndDeleteExistingApplicationAuthorization(
     this IObservableAuthorizationsClient authorizationsClient,
     string clientId,
     string clientSecret,
     NewAuthorization newAuthorization,
     Func<TwoFactorAuthorizationException, IObservable<TwoFactorChallengeResult>> twoFactorChallengeHandler,
     bool retryInvalidTwoFactorCode)
 {
     return authorizationsClient.CreateAndDeleteExistingApplicationAuthorization(
         clientId,
         clientSecret,
         newAuthorization,
         twoFactorChallengeHandler,
         null,
         retryInvalidTwoFactorCode);
 }