diff --git a/aspnetcore/mvc/models/file-uploads.md b/aspnetcore/mvc/models/file-uploads.md index 307dfbf0d9fd..f228c95b15de 100644 --- a/aspnetcore/mvc/models/file-uploads.md +++ b/aspnetcore/mvc/models/file-uploads.md @@ -415,6 +415,47 @@ The preceding example is similar to a scenario demonstrated in the sample app: ### Upload large files with streaming +For scenarios where large file uploads are required, streaming uploads allow you to process incoming multipart form data directly without buffering the entire file in memory or on disk via model binding. This technique is especially important for files that could exceed server or framework buffering thresholds. + +The [sample application for 9.x](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/mvc/models/file-uploads/samples/9.x/FileManagerSample) demonstrates how a server can receive a file and stream the data directly to disk, supporting robust cancellation via the HTTP request's cancellation token. + + is an ASP.NET Core utility for reading files from incoming requests. The following snippet shows how to process a request and stream the file into an `outputStream` (such as a ): + +```csharp +// Read the boundary from the Content-Type header +var boundary = HeaderUtilities.RemoveQuotes( + MediaTypeHeaderValue.Parse(request.ContentType).Boundary).Value; + +// Use MultipartReader to stream data to a destination +var reader = new MultipartReader(boundary, Request.Body); +MultipartSection? section; + +while ((section = await reader.ReadNextSectionAsync(cancellationToken)) != null) +{ + var contentDisposition = section.GetContentDispositionHeader(); + + if (contentDisposition != null && contentDisposition.IsFileDisposition()) + { + await section.Body.CopyToAsync(outputStream, cancellationToken); + } +} +``` + + is a wrapper around that doesn't require you to write manual request body parsing code. You can use its method to populate the request's form data, then access uploaded files from the built-in collection: + +```csharp +// Get the IFormFeature and read the form +var formFeature = Request.HttpContext.Features.GetRequiredFeature(); +await formFeature.ReadFormAsync(cancellationToken); + +// Access the uploaded file (example: first file) +var filePath = Request.Form.Files.First().FileName; + +return Results.Ok($"Saved file at {filePath}"); +``` + +For advanced scenarios, manually parse the raw request body using , which exposes an [`IPipeReader`](/aspnet/core/fundamentals/middleware/request-response) for low-level, high-performance streaming. The sample app includes endpoint handlers that use `IPipeReader` in both minimal APIs and controllers. + The [3.1 example](https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/mvc/models/file-uploads/samples/3.x/SampleApp/Pages/StreamedSingleFileUploadDb.cshtml) demonstrates how to use JavaScript to stream a file to a controller action. The file's antiforgery token is generated using a custom filter attribute and passed to the client HTTP headers instead of in the request body. Because the action method processes the uploaded data directly, form model binding is disabled by another custom filter. Within the action, the form's contents are read using a `MultipartReader`, which reads each individual `MultipartSection`, processing the file or storing the contents as appropriate. After the multipart sections are read, the action performs its own model binding. The initial page response loads the form and saves an antiforgery token in a cookie (via the `GenerateAntiforgeryTokenCookieAttribute` attribute). The attribute uses ASP.NET Core's built-in [antiforgery support](xref:security/anti-request-forgery) to set a cookie with a request token: diff --git a/aspnetcore/security/authentication/social/google-logins.md b/aspnetcore/security/authentication/social/google-logins.md index eb5385d4a677..285fd2639bbc 100644 --- a/aspnetcore/security/authentication/social/google-logins.md +++ b/aspnetcore/security/authentication/social/google-logins.md @@ -4,85 +4,116 @@ author: rick-anderson description: This tutorial demonstrates the integration of Google account user authentication into an existing ASP.NET Core app. ms.author: riande ms.custom: mvc -ms.date: 3/3/2022 +ms.date: 06/18/2025 uid: security/authentication/google-logins --- # Google external login setup in ASP.NET Core -By [Valeriy Novytskyy](https://github.com/01binary), [Rick Anderson](https://twitter.com/RickAndMSFT) and [Sharaf Abacery](https://github.com/sharafabacery) +By [Valeriy Novytskyy](https://github.com/01binary), [Rick Anderson](https://twitter.com/RickAndMSFT), and [Sharaf Abacery](https://github.com/sharafabacery) -This tutorial shows you how to enable users to sign in with their Google account using the ASP.NET Core project created on the [previous page](xref:security/authentication/social/index). +This tutorial shows how to enable user sign in with Google accounts using a sample ASP.NET Core project created in . Follow Google's official guidance in [Sign in with Google for Web: Setup](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid) to create a Google API client ID. -## Create the Google OAuth 2.0 Client ID and secret +## Create the app in Google -* Follow the guidance in [Integrating Google Sign-In into your web app](https://developers.google.com/identity/gsi/web/guides/overview) (Google documentation) -* Go to [Google API & Services](https://console.cloud.google.com/apis). -* A **Project** must exist first, you may have to create one. Once a project is selected, enter the **Dashboard**. +* Navigate to the [Google API & Services](https://console.cloud.google.com/apis) page of the Google Cloud platform. +* If no project exists, create a new project by selecting the **Create Project** button. To select a different project than an existing project that loads, select the loaded project's button in the top-left corner of the UI, followed by the project. To add a new project, select the loaded project's button in the top-left corner of the UI, followed by the **New project** button. +* When creating a new project: + * Enter a **Project name**. + * Optionally, select an **Organization** for the project. + * Select the **Create** button. -* In the **OAuth consent screen** of the **Dashboard**: - * Select **User Type - External** and **CREATE**. - * In the **App information** dialog, Provide an **app name** for the app, **user support email**, and **developer contact information**. - * Step through the **Scopes** step. - * Step through the **Test users** step. - * Review the **OAuth consent screen** and go back to the app **Dashboard**. +After creating the project, the **Dashboard** page of the project loads, where it's possible to configure the project. -* In the **Credentials** tab of the application Dashboard, select **CREATE CREDENTIALS** > **OAuth client ID**. -* Select **Application type** > **Web application**, choose a **name**. -* In the **Authorized redirect URIs** section, select **ADD URI** to set the redirect URI. Example redirect URI: `https://localhost:{PORT}/signin-google`, where the `{PORT}` placeholder is the app's port. -* Select the **CREATE** button. -* Save the **Client ID** and **Client Secret** for use in the app's configuration. -* When deploying the site, either: - * Update the app's redirect URI in the **Google Console** to the app's deployed redirect URI. - * Create a new Google API registration in the **Google Console** for the production app with its production redirect URI. +Open the **Credentials** tab to create the OAuth client. + +The prerequisite to creating the credentials is to configure the OAuth consent screen. If the consent isn't configured, there's a prompt to configure the consent screen. + +* Select **Configure consent screen** or select **OAuth consent screen** in the sidebar. +* In the **OAuth consent screen**, select **Get started**. +* Set the **App name** and **User support email**. +* Set the audience type to **External**. +* Add **Contact information** by entering a contact email address. +* Agree to the terms. +* Select **Create**. + +Create the client credentials for the app by opening the **Clients** sidebar menu item: + +* Select the **Create client** button. +* Select **Web application** as the **Application type**. +* Enter a **Name** for the client. +* Add an **Authorized redirect URI**. For local testing, use the default address `https://localhost:{PORT}/signin-google`, where the `{PORT}` placeholder is the app's port. +* Select the **Create** button to create the client. +* Save the **Client ID** and **Client secret**, which are used later in the ASP.NET app configuration. + +> [!NOTE] +> The URI segment `/signin-google` is set as the default callback of the Google authentication provider. It's possible to change the default callback URI while configuring the Google authentication middleware via the inherited property of the class. + +When deploying the app, either: + +* Update the app's redirect URI in the **Google Console** to the app's deployed redirect URI. +* Create a new Google API registration in the **Google Console** for the production app with its production redirect URI. ## Store the Google client ID and secret -Store sensitive settings such as the Google client ID and secret values with [Secret Manager](xref:security/app-secrets). For this sample, use the following steps: +Store sensitive settings, such as the Google client ID and secret values, with [Secret Manager](xref:security/app-secrets). For this sample, follow these steps: -1. Initialize the project for secret storage per the instructions at [Enable secret storage](xref:security/app-secrets#enable-secret-storage). -1. Store the sensitive settings in the local secret store with the secret keys `Authentication:Google:ClientId` and `Authentication:Google:ClientSecret`: +1. Initialize the project for secret storage according to the instructions in . +1. Store the sensitive settings in the local secret store with the secret keys `Authentication:Google:ClientId` (value: `{CLIENT ID}` placeholder) and `Authentication:Google:ClientSecret` (value: `{CLIENT SECRET}` placeholder): ```dotnetcli - dotnet user-secrets set "Authentication:Google:ClientId" "" - dotnet user-secrets set "Authentication:Google:ClientSecret" "" + dotnet user-secrets set "Authentication:Google:ClientId" "{CLIENT ID}" + dotnet user-secrets set "Authentication:Google:ClientSecret" "{CLIENT SECRET}" ``` [!INCLUDE[](~/includes/environmentVarableColon.md)] -You can manage your API credentials and usage in the [API Console](https://console.developers.google.com/apis/dashboard). +Manage API credentials and usage in the [API Console](https://console.developers.google.com/apis/dashboard). ## Configure Google authentication -* Add the [`Google.Apis.Auth.AspNetCore3`](https://www.nuget.org/packages/Google.Apis.Auth.AspNetCore3) NuGet package to the app. -* Add the Authentication service to the `program.cs`: -* Follow [`Add Authentication for asp.net app`](https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#configure-your-application-to-use-google.apis.auth.aspnetcore3) +:::moniker range=">= aspnetcore-6.0" -[!INCLUDE [default settings configuration](includes/default-settings2-2.md)] +Add the authentication service to the `Program` file: -## Sign in with Google -* Get a link to the library at [Google Developer Library](https://developers.google.com/identity/gsi/web/guides/client-library). -* Then go to [Google Developer Button Generation](https://developers.google.com/identity/gsi/web/tools/configurator). -* Setup your Controller to match the `data-login_uri="{HostName}/{ControllerName}/{actionName}"` attribute, as it will forward you to that link after a successful login. -* Create a controller and action that takes one argument `string credential`, which is returned by Google upon completing the login process. -* Verify the `credential` using the following line of code: -`GoogleJsonWebSignature.Payload payload = await GoogleJsonWebSignature.ValidateAsync(credential);` -* This will retrieve the available information about the logged-in user, which could then be stored in a database. +:::code language="csharp" source="~/security/authentication/social/social-code/6.x/ProgramGoogle.cs" id="snippet1"::: +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +Add the authentication service to `Startup.ConfigureServices`: + +```csharp +services.AddAuthentication().AddGoogle(googleOptions => +{ + googleOptions.ClientId = configuration["Authentication:Google:ClientId"]; + googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"]; +}); +``` + +:::moniker-end + +[!INCLUDE [default settings configuration](includes/default-settings.md)] + +## Sign in with Google -## Change the default callback URI +* Run the app and select **Log in**. +* Under **Use another service to log in.**, select Google. +* The browser is redirected to **Google** for authentication. +* Select the Google account to log in or enter Google credentials. +* If this is the first time signing in, there's a prompt to allow the app to access the Google account information. +* The browser is redirected back to the app, where it's possible to set the email. -The URI segment `/signin-google` is set as the default callback of the Google authentication provider. You can change the default callback URI while configuring the Google authentication middleware via the inherited property of the class. +The user is now logged in using Google credentials. ## Troubleshooting -* If the sign-in doesn't work and you aren't getting any errors, switch to development mode to make the issue easier to debug. -* If Identity isn't configured by calling `services.AddIdentity` in `ConfigureServices`, attempting to authenticate results in *ArgumentException: The 'SignInScheme' option must be provided*. The project template used in this tutorial ensures Identity is configured. -* If the site database has not been created by applying the initial migration, you get *A database operation failed while processing the request* error. Select **Apply Migrations** to create the database, and refresh the page to continue past the error. -* HTTP 500 error after successfully authenticating the request by the OAuth 2.0 provider such as Google: See [this GitHub issue](https://github.com/dotnet/AspNetCore.Docs/issues/14169). -* How to implement external authentication with Google for React and other SPA apps: See [this GitHub issue](https://github.com/dotnet/AspNetCore.Docs/issues/14169). +* If the sign-in doesn't work without receiving any errors, switch to development mode to make the app and Google registration easier to debug. +* If the site's database hasn't been created by applying the initial migration, the following error occurs: *A database operation failed while processing the request*. Select **Apply Migrations** to create the database and refresh the page to continue past the error. +* For information about an HTTP 500 error after successfully authenticating the request by the OAuth 2.0 provider, such as Google, and information on how to implement external authentication with Google for React and other SPA apps, see [Middleware not handling 'signin-google' route after successful authentication in Asp.Net Core Web Api External Login Authentication (`dotnet/AspNetCore.Docs` #14169)](https://github.com/dotnet/AspNetCore.Docs/issues/14169). ## Next steps -* This article showed how you can authenticate with Google. You can follow a similar approach to authenticate with other providers listed on the [previous page](xref:security/authentication/social/index). -* Once you publish the app to Azure, reset the `ClientSecret` in the Google API Console. -* Set the `Authentication:Google:ClientId` and `Authentication:Google:ClientSecret` as application settings in the Azure portal. The configuration system is set up to read keys from environment variables. +* This article demonstrates authentication with Google. For information on authenticating with other external providers, see . +* After the app is deployed to Azure, reset the `ClientSecret` in the Google API console. +* Set the `Authentication:Google:ClientId` and `Authentication:Google:ClientSecret` as app settings in the Azure portal. The configuration system is set up to read keys from the environment variables. diff --git a/aspnetcore/security/authentication/social/social-code/6.x/ProgramGoogle.cs b/aspnetcore/security/authentication/social/social-code/6.x/ProgramGoogle.cs index f91d0416da8a..ab8f7166ea18 100644 --- a/aspnetcore/security/authentication/social/social-code/6.x/ProgramGoogle.cs +++ b/aspnetcore/security/authentication/social/social-code/6.x/ProgramGoogle.cs @@ -2,8 +2,10 @@ var services = builder.Services; var configuration = builder.Configuration; +// services.AddAuthentication().AddGoogle(googleOptions => - { - googleOptions.ClientId = configuration["Authentication:Google:ClientId"]; - googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"]; - }); +{ + googleOptions.ClientId = configuration["Authentication:Google:ClientId"]; + googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"]; +}); +//