Back to "Προσθήκη Google Auth χωρίς ASP.NET Identity Database"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET Google Auth

Προσθήκη Google Auth χωρίς ASP.NET Identity Database

Monday, 05 August 2024

Εισαγωγή

Σε αυτή την εφαρμογή ήθελα να προσθέσω έναν απλό μηχανισμό για να επιτρέψω τη σύνδεση να προστεθεί σχόλια ( και μερικά διοικητικά καθήκοντα) στην εφαρμογήM SK2 θέλησα να χρησιμοποιήσω το Google Auth για αυτό το σκοπόMSKA3 δεν θέλω να χρησιμοποιώ τη βάση δεδομένων ταυτότητας ASP

Οι βάσεις δεδομένων είναι ένα ισχυρό συστατικό οποιασδήποτε εφαρμογής, αλλά προσθέτουν επίσης πολυπλοκότητα. θέλω να αποφύγω αυτή την πολυπλότητα μέχρι που πραγματικά χρειαζόμουνΜSK1

Βήματα

Πρώτα πρέπει να εγκαταστήσετε το Google Auth στην κονσόλα προγραμματιστών του Google. Μπορείτε να ακολουθήσετε τα βήματα σε αυτό Link Για να δημιουργήσετε τις λεπτομέρειες σας για εσάς το Google Client ID και Secret.

Μόλις έχετε το Google Client ID και Secret, μπορείτε να τα προσθέσετε στις ρυθμίσεις εφαρμογών σαςΜSK1 αρχείο

    "Auth" :{
"GoogleClientId": "",
"GoogleClientSecret": ""
}

ΠΩΣ ΔΕΝ πρέπει να ελέγξετε αυτά για τον έλεγχο πηγής. Αντί της τοπικής ανάπτυξης μπορείτε να χρησιμοποιήσετε το αρχείο Secrets:

secrets.png

Εκεί μπορείτε να προσθέσετε το Google Client ID και Secret ( αναφέρετε ότι το ID του πελάτη σας δεν είναι ' αναφέρεται πραγματικά εμπιστευτικό , αναφερόμενων όπως θα αναφέρω' αναμένεται να δείτε αργότερα ότι η ' αναφέρει συμπεριλαμβανόμενη στην κλήση JS στο μπροστινό άκρο της . αναφέρονται

    "Auth" :{
  "GoogleClientId": "ID",
  "GoogleClientSecret": "CLIENTSECRET"
}

Προσαρμογή του Google Auth με το POCO

Σημείωση: Χρησιμοποιώ μια τροποποιημένη έκδοση του Steve Smith' IConfigSection ( πρόσφατα έγινε διάσημο από τον Phil Haack Αυτό είναι για να αποφύγετε τα IOptions πράγματα που βρίσκω λίγο κρυφά ( και σπάνια χρειάζονται, καθώς σχεδόν ποτέ δεν αλλάζω τη διαμόρφωση μετά την εκτέλεση στα σενάρια μουΜSK1

Στο δικό μου κάνω αυτό που με επιτρέπει να πάρω το όνομα του τμήματος από την ίδια την τάξη:

Click to expand


namespace Mostlylucid.Config;

public static class ConfigExtensions {
    public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfiguration configuration)
        where TConfig : class, new() {
        if (services == null) throw new ArgumentNullException(nameof(services));
        if (configuration == null) throw new ArgumentNullException(nameof(configuration));
        
        var config = new TConfig();
        configuration.Bind(config);
        services.AddSingleton(config);
        return config;
    }
    
    public static TConfig Configure<TConfig>(this WebApplicationBuilder builder)
        where TConfig : class, IConfigSection, new() {
        var services = builder.Services;
        var configuration = builder.Configuration;
        var sectionName = TConfig.Section;
        return services.ConfigurePOCO<TConfig>(configuration.GetSection(sectionName));
    }
    

    public static TConfig GetConfig<TConfig>(this WebApplicationBuilder builder)
        where TConfig : class, IConfigSection, new() {
        var configuration = builder.Configuration;
        var sectionName = TConfig.Section;
        var section = configuration.GetSection(sectionName).Get<TConfig>();
        return section;
        
    }
    
    public static Dictionary<string, object> GetConfigSection(this IConfiguration configuration, string sectionName) {
        var section = configuration.GetSection(sectionName);
        var result = new Dictionary<string, object>();
        foreach (var child in section.GetChildren()) {
            var key = child.Key;
            var value = child.Value;
            result.Add(key, value);
        }
        
        return result;
    }
    
    public static Dictionary<string, object> GetConfigSection<TConfig>(this WebApplicationBuilder builder)
        where TConfig : class, IConfigSection, new() {
        var configuration = builder.Configuration;
        var sectionName = TConfig.Section;
        return configuration.GetConfigSection(sectionName);
    }
}

public interface IConfigSection {
    public static abstract string Section { get; }
}
Το αυτί μου φαίνεται
public class Auth : IConfigSection
{
    public static string Section => "Auth";
    public string GoogleClientId { get; set; }
    public string GoogleClientSecret { get; set; }
    
    public string AdminUserGoogleId { get; set; }
    
}

Πού χρησιμοποιώ μια στατική μέθοδο διεπαφής για να πάρω το όνομα τμήματος.

Στη συνέχεια στο startup μου μπορώ να το κάνω αυτό:

var auth = builder.GetConfig<Auth>();

ΕΠΙΣΤΡΟΦΗ ΣΤΟ ΝΕΟ ΠΡΟΣ ΤΟΝ Google!

Το πρόγραμμα.cs Setup

Πράγματι, προσθέστε αυτό

services.AddCors(options =>
{
    options.AddPolicy("AllowMostlylucid",
        builder =>
        {
            builder.WithOrigins("https://www.mostlylucid.net")
                .WithOrigins("https://mostlylucid.net")
                .WithOrigins("https://localhost:7240")
                .AllowAnyHeader()
                .AllowAnyMethod();
        });
});

builder.Services
    .AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
   
      
    })
    .AddCookie()
    .AddGoogle(options =>
    {
        options.ClientId = auth.GoogleClientId;
        options.ClientSecret = auth.GoogleClientSecret;
    });

Σας αρέσει' αναμένεται να σημειώσετε ότι το ' αναφέρει τις εγγραφές CORS εδώ, το , αναμένετε ότι θα πρέπει επίσης να τις εγκαταστήσετε στην κονσόλα ταυτότητας της Google, ειδικά στο ..

googleidentity.png

Αυτό εξασφαλίζει ότι το Google Auth μπορεί να χρησιμοποιηθεί μόνο από τους τομείς που καθορίζετε.

Το Google Auth στο Razor

Στο δικό μου _Layout.cshtml Έχω αυτό το JavascriptΜSK1 αυτό είναι όπου εγκαθιστώ τα Google Buttons μου και εκκινώ μια κλήση που καταγράφει την εφαρμογή ASP.NET appM SK3

Το Google JS

<script src="https://accounts.google.com/gsi/client" async defer></script>

Αυτός είναι ο λόγος για τον κωδικό παρακάτω



        
        function renderButton(element)
        {
            google.accounts.id.renderButton(
                element,
                {
                    type: "standard",
                    size: "large",
                    width: 200,
                    theme: "filled_black",
                    text: "sign_in_with",
                    shape: "rectangular",
                    logo_alignment: "left"
                }
            );
        }
        function initGoogleSignIn() {
            google.accounts.id.initialize({
                client_id: "839055275161-u7dqn2oco2729n6i5mk0fe7gap0bmg6g.apps.googleusercontent.com",
                callback: handleCredentialResponse
            });
            const element = document.getElementById('google_button');
            if (element) {
                renderButton(element);
            }
            const secondElement = document.getElementById('google_button2');
            if (secondElement) {
                renderButton(secondElement);
            }
           
        }

        function handleCredentialResponse(response) {
            if (response.credential) {
                const xhr = new XMLHttpRequest();
                xhr.open('POST', '/login', true);
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.onload = function () {
                    if (xhr.status === 200) {
                        window.location.reload();
                    } else {
                        console.error('Failed to log in.');
                    }
                };
                xhr.send(JSON.stringify({ idToken: response.credential }));
            } else {
                console.error('No credential in response.');
            }
        }

        window.onload = initGoogleSignIn;

Εδώ μπορείτε να δείτε ότι έχω έως και δύο στοιχεία div στη σελίδα με το ID google_button και googleΜSK1buton2.Αυτά είναι τα στοιχεία που η Google JS θα μετατρέψει τα κουμπιά σεM SK3

TIP: Εάν χρησιμοποιείτε το Tailwind, μπορείτε να ρίξετε το κουμπί div για να λειτουργήσει σωστά σε σκοτεινό τρόπο M SK2Αλλιώς καθιστά ένα λευκό υπόβαθρο γύρω από τον κουμπόΜSK3

<div class="w-[200px] h-[39px] overflow-hidden rounded">
    <div id="google_button">
    </div>
</div>

Στο παραπάνω JavaScript δημοσιεύω αυτό πίσω σε μια δράση του Ελέγχου που ονομάζεται Login.Αυτό είναι όπου χειρίζομαι το Google Auth.

      const xhr = new XMLHttpRequest();
                xhr.open('POST', '/login', true);
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.onload = function () {
                    if (xhr.status === 200) {
                        window.location.reload();
                    } else {
                        console.error('Failed to log in.');
                    }
                };
                xhr.send(JSON.stringify({ idToken: response.credential }));

Το Google Auth στο διαχειριστή

Ο ελεγκτής είναι εδώ' αυτόΜSK1 αρκετά απλό απλά παίρνει το δημοσιευμένο JWT, αποκωδικοποιεί τότε χρησιμοποιεί ότι για να συνδεθείτε στην εφαρμογήM SK3

    [Route("login")]
        [HttpPost]
        public async Task<IActionResult> HandleGoogleCallback([FromBody] GoogleLoginRequest request)
        {
            var handler = new JwtSecurityTokenHandler();
            var jsonToken = handler.ReadToken(request.IdToken) as JwtSecurityToken;

            if (jsonToken == null)
            {
                return BadRequest("Invalid token");
            }

            var claimsIdentity = new ClaimsIdentity(
                jsonToken.Claims,
                GoogleDefaults.AuthenticationScheme);

            var authProperties = new AuthenticationProperties
            {
                IsPersistent = true
            };

            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(claimsIdentity),
                authProperties);

            return Ok();
        }
    }

ΣΗΜΕΙΩΣΗ: Αυτό δεν είναι'τ prefect καθώς ταιριάζει τα ονόματα των ισχυρισμών M SK2they είναι όλα κατώτερη περίπτωσηMSKA3 αλλά λειτουργεί για τώραMKA4

Κλάση βάσης ελέγχου για την εξαγωγή των ιδιοτήτων σύνδεσης

Στο BaseController μου εξάγω τις ιδιότητες που χρειάζομαι;

      public record LoginData(bool loggedIn, string? name, string? avatarUrl, string? identifier);
    
    protected LoginData GetUserInfo()
    {
        var authenticateResult = HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme).Result;
        if (authenticateResult.Succeeded)
        {
            var principal = authenticateResult.Principal;
            if(principal == null)
            {
                return new LoginData(false, null, null, null);
            }
            var name = principal.FindFirst("name").Value;
            var avatarUrl =principal.FindFirst("picture").Value;
            var nameIdentifier = principal.FindFirst("sub");
            return new LoginData(true, name, avatarUrl, nameIdentifier?.Value);
        }
        return new LoginData(false,null,null,null);
    }

Αυτό σας επιτρέπει να χρησιμοποιήσετε το Gooogle Authentication χωρίς τη χρήση της ASP για το . για την βάση δεδομένων ταυτότητας του .

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.