// This method gets called by the runtime. Use this method to configure the HTTP request pipeline
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            // Add cookie middleware
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AutomaticAuthenticate = true,
                AutomaticChallenge    = true,
                LoginPath             = new PathString("/login"),
                LogoutPath            = new PathString("/logout")
            });

            // Add the OAuth2 middleware
            app.UseOAuthAuthentication(new OAuthOptions
            {
                AuthenticationScheme = "Coinbase",

                ClientId     = Configuration["coinbase:clientId"],
                ClientSecret = Configuration["coinbase:clientSecret"],

                CallbackPath = new PathString("/signin-coinbase"),


                AuthorizationEndpoint = "https://www.coinbase.com/oauth/authorize",
                TokenEndpoint         = "https://api.coinbase.com/oauth/token",
                // the URL accessed used after user authenticated, used to store user object
                UserInformationEndpoint = "https://api.coinbase.com/v2/user",
                // in the example, this was written like: "https://sandbox.coinbase.com/v2/user/(id,name,username)" to store fields as "claims"

                // SCOPE
                // additional scopes needed for live money send { "meta[send_limit_amount]=1", "eta[send_limit_currency]=USD", "meta[send_limit_period]=day" }
                // Scope = { "user", "addresses", "balance", "contacts", "recurring_payments", "transactions", "wallet:accounts:read", "wallet:transactions:read", "wallet:transactions:send:bypass-2fa", "wallet:transactions:send", "meta[send_limit_amount]=10", "eta[send_limit_currency]=USD", "meta[send_limit_period]=day" },
                Scope = { "wallet:accounts:read", "wallet:transactions:read", "wallet:transactions:send" },
                // Scope = { "wallet:accounts:read", "wallet:transactions:read" },


                Events = new OAuthEvents
                {
                    // The OnCreatingTicket event is called after the user has been authenticated and the OAuth middleware has
                    // created an auth ticket. We need to manually call the UserInformationEndpoint to retrieve the user's information,
                    // parse the resulting JSON to extract the relevant information, and add the correct claims.
                    OnCreatingTicket = async context =>
                    {
                        // Retrieve user info from Coinbase after successful authentication
                        var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                        request.Headers.Add("x-li-format", "json"); // Tell Coinbase we want the result in JSON, otherwise it will return XML

                        var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted);
                        response.EnsureSuccessStatusCode();

                        // Extract the user info object
                        var user = JObject.Parse(await response.Content.ReadAsStringAsync());

                        // testing JObject/JToken variations
                        string fullName = (string)user["data"]["name"];
                        string gravatar = (string)user["data"]["avatar_url"];
                        JToken tData    = user["data"];


                        var fullData  = user["data"];
                        string userId = (string)user["data"]["id"];
                        // var userId = user["data"]["id"].ToObject();

                        // import database context
                        var optionsBuilder = new DbContextOptionsBuilder <BCAPContext>();
                        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=BCAPDB;Trusted_Connection=True;");
                        BCAPContext BCAP = new BCAPContext(optionsBuilder.Options);

                        // Query the singular entry in current customer table
                        var currentUser = BCAP.CurrentCustomer.FirstOrDefault();

                        // add user object into currentUser table if not present, else if present, updates to currently pulled user info
                        if (currentUser == null)
                        {
                            BCAP.CurrentCustomer.Add(new CurrentCustomer
                            {
                                CustomerId    = userId,
                                FullName      = fullName,
                                ProfilePicUrl = gravatar,
                                Data          = fullData.ToString(),
                                AccessToken   = context.AccessToken
                            });
                        }
                        else
                        {
                            // update currentUser from database
                            BCAP.CurrentCustomer.Remove(currentUser);
                            BCAP.SaveChanges();
                            BCAP.CurrentCustomer.Add(new CurrentCustomer
                            {
                                CustomerId    = userId,
                                FullName      = fullName,
                                ProfilePicUrl = gravatar,
                                Data          = fullData.ToString(),
                                AccessToken   = context.AccessToken
                            });
                        }
                        BCAP.SaveChanges();

                        // Add the Name Identifier claim
                        if (!string.IsNullOrEmpty(userId))
                        {
                            context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId, ClaimValueTypes.String, context.Options.ClaimsIssuer));
                        }

                        // Add the Name claim
                        var formattedName = user["data"]["name"].ToString();
                        // var formattedName = user.Value<string>("formattedName");
                        if (!string.IsNullOrEmpty(formattedName))
                        {
                            context.Identity.AddClaim(new Claim(ClaimTypes.Name, formattedName, ClaimValueTypes.String, context.Options.ClaimsIssuer));
                        }

                        context.Identity.AddClaim(new Claim("urn:token:coinbase", context.AccessToken));
                    },

                    OnRedirectToAuthorizationEndpoint = context =>

                    {
                        // metaTags required by coinbase (in tandem with Scope parameter) to allow transactions
                        var metaTags = "&meta%5Bsend_limit_amount%5D=1&meta%5Bsend_limit_currency%5D=USD&meta%5Bsend_limit_period%5D=day";
                        var newUri   = context.RedirectUri + metaTags;
                        context.Response.Redirect(newUri);
                        return(Task.FromResult(0));
                    }
                }
            });

            // Listen for requests on the /login path, and issue a challenge to log in with Coinbase middleware
            app.Map("/login", builder =>
            {
                builder.Run(async context =>
                {
                    // Return a challenge to invoke the Coinbase authentication scheme
                    // await context.Authentication.ChallengeAsync("Coinbase", properties: new AuthenticationProperties() { RedirectUri = "/" });
                    await context.Authentication.ChallengeAsync("Coinbase", properties: new AuthenticationProperties()
                    {
                        RedirectUri = "http://*****:*****@"Server=(localdb)\mssqllocaldb;Database=BCAPDB;Trusted_Connection=True;");
                    BCAPContext BCAP = new BCAPContext(optionsBuilder.Options);

                    // define and clear current customer
                    var currentUser = BCAP.CurrentCustomer.FirstOrDefault();
                    BCAP.CurrentCustomer.Remove(currentUser);
                    BCAP.SaveChanges();


                    // Sign the user out of the authentication middleware (i.e. it will clear the Auth cookie)
                    await context.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

                    // Redirect the user to the home page after signing out
                    // context.Response.Redirect("/");
                    context.Response.Redirect("http://localhost:8080/#/register");
                });
            });

            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseApplicationInsightsRequestTelemetry();

            app.UseApplicationInsightsExceptionTelemetry();

            app.UseMvc();
        }
Exemple #2
0
 public CustomerController(BCAPContext context)
 {
     _context = context;
 }