• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Autoryzacja dla endpointa w api napisanym w Asp.Net

Object Storage Arubacloud
0 głosów
362 wizyt
pytanie zadane 7 maja 2020 w C# przez Moras Obywatel (1,620 p.)

Tworzę sobię backend w ASP.Net z autoryzacją. Do zrobienia tego skorzystałem z tego - https://jasonwatmore.com/post/2019/10/14/aspnet-core-3-simple-api-for-authentication-registration-and-user-management#running-react

Zrobiłem sobie endpoint do dodawania zdjęcia na serwer dla konkretnego usera:

 [Authorize]
        [HttpPost("{username}/photos/")]
        public IActionResult AddPhoto(String username, [FromForm]IFormFile photo)
        {
         
            //add img to static folder
            var wwww_root = _webHostEnvironment.WebRootPath;
            var path = @"\profiles\" + username + @"\profile_photos\";
            var upload_path = wwww_root + path;

            var pathForFile = upload_path + photo.FileName;

            try
            {
                using (FileStream fileStream = System.IO.File.Create(pathForFile))
                {
                    photo.CopyTo(fileStream);
                    fileStream.Flush();
                }
            }
            catch(DirectoryNotFoundException e)
            {
                return NotFound("This username does not exists");
            }
            var pathOnServer = "http://" + Request.Host.Value + path + photo.FileName;
            var photoImage = _profileService.AddPhoto(username, pathOnServer);
            
            return Ok();

        }

i to działa, ale chciałbym by dla podanego username był wymagany Bearer Token, bo w tym wypadku owszej jest wymagany bearer token, ale działa dla wszystkich tokenów. By jaśniej zoobrazować sytuację:

Mam endpoint - http://localhost:4000/profiles/{username}/photos/

jeśli jako username podam np. admin chciałbym by był wymagany token przypisany właśnie dla admina, a tokeny innych użytkowników były odrzucane.

W podanym linku znalazłem konfigurację dla autentyfikacji

// configure jwt authentication
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.Events = new JwtBearerEvents
                {
                    OnTokenValidated = context =>
                    {
                        var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>();
                        var userId = int.Parse(context.Principal.Identity.Name);
                        var user = userService.GetById(userId);
                        if (user == null)
                        {
                            // return unauthorized if user no longer exists
                            context.Fail("Unauthorized");
                        }
                        return Task.CompletedTask;
                    }
                };
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });

i metodę w kontrolerze do wywołania autentykacji

[AllowAnonymous]
        [HttpPost("authenticate")]
        public IActionResult Authenticate([FromBody]AuthenticateModel model)
        {
            var user = _userService.Authenticate(model.Username, model.Password);

            if (user == null)
                return BadRequest(new { message = "Username or password is incorrect" });

            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                    new Claim(ClaimTypes.Name, user.Id.ToString())
                }),
                Expires = DateTime.UtcNow.AddDays(7),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            var tokenString = tokenHandler.WriteToken(token);

            // return basic user info and authentication token
            return Ok(new
            {
                Id = user.Id,
                Username = user.Username,
                FirstName = user.FirstName,
                LastName = user.LastName,
                Token = tokenString
            });
        }

ale nie potrafię tego przełożyć na rozwiązanie mojego problemu. Bardzo proszę o wskazówki jak to moge zrobić.

komentarz 7 maja 2020 przez NowyUrzydgownig Mądrala (5,090 p.)
Jak dajesz AllowAnonymous, to uwierzytelnianie jest pomijane, czyli autoryzacja nie zachodzi.
komentarz 7 maja 2020 przez Moras Obywatel (1,620 p.)
tak, ale to metoda która tworzy token uwierzytelniający więc nie może być autoryzowana
komentarz 7 maja 2020 przez NowyUrzydgownig Mądrala (5,090 p.)
No to jest prawidłowo reszta.
komentarz 7 maja 2020 przez Moras Obywatel (1,620 p.)
Ale nie wiem jak zrobić tak jak chcę czyli. Mam tu endpointa do wysyłania zdjęcia na serwer

http://localhost:4000/profiles/{username}/photos/

Po zalogowaniu się na moją stronę użytkownik w odpowiedzi dostaje token wygenerowany przez metodę "Authenticate". Teraz chcę by użytkownik mógł dodać do swojego profilu zdjęcie dlatego client skorzysta z endpointa podanego wyżej i tu potrzebna jest autoryzacja by nie doszło do tego, że inny użytkownik za pomocą swojego tokena doda zdjęcie do innego profilu.
komentarz 7 maja 2020 przez Ehlert Ekspert (212,670 p.)
Po co parametr username w uri? Usera wyciągasz z tokena, więc sprawdzenie o którym mówisz będzie zbędne.
komentarz 7 maja 2020 przez Moras Obywatel (1,620 p.)
Tylko, pod tym linkiem który wysłałem token nie jest trzymany w bazie, więc powinienem go tam umieszczać po każdym zalogowaniu użytkownika i w body przekazywać jedynie token zalogowanego użytkownika i sprawdzać czy jest w bazie?

1 odpowiedź

0 głosów
odpowiedź 7 maja 2020 przez Ehlert Ekspert (212,670 p.)

Daną która identyfikuje usera przesyłaj w nagłówkach. Mamy tutaj dwa podstawowe podejścia:

  1. Stateful: wysyłasz userowi jakiś długi łańcuch będący id jego sesji. Wtedy informację o tym czy jest zalogowany trzymasz po stronie serwera. Dla wygody najczęściej wykorzystuje się ciacho.
  2. Stateless: wysyłasz do usera token podpisany przez Twój backend. Kiedy user wysyła do Ciebie ten token jesteś w stanie zweryfikować, czy został on wystawiony przez Ciebie i kim jest user. W tym przypadku sesja jest po stronie użytkownika. 
komentarz 7 maja 2020 przez Moras Obywatel (1,620 p.)
Robiłem na podstawie tego artykuły, który podlinkowałem. Tam serwer na podstawie ID użytkownika generuje JWT token. Z kolei dane o zalogowanym użytkowniku są trzymane w localStorage. Czyli wychodzi na to, że jest to podejście "Stateless". Więc reasumując - powinienem w nagłówku przesłać na serwer token użytkownika, który jest zalogowany i serwer odszyfrowuje go i weryfikuje jego poprawność?
komentarz 7 maja 2020 przez Ehlert Ekspert (212,670 p.)
Sprawdza podpis. Ale jest tak jak powiedziałeś. Podejście stateless. Wobec tego jeśli masz usera z tokena, to nie widzę potrzeby aby przekazywać username w uri.

Gdzieś tam widziałem warianty z całkowitym szyfrowaniem tokena, bo w standardowym jwt jesteś w stanie zobaczyć jakie informacje są przechowywane po stronie klienta.

Podobne pytania

+1 głos
1 odpowiedź 675 wizyt
0 głosów
2 odpowiedzi 420 wizyt
pytanie zadane 20 grudnia 2020 w C# przez czujek22 Dyskutant (7,670 p.)
0 głosów
0 odpowiedzi 406 wizyt
pytanie zadane 4 maja 2018 w Nasze projekty przez marcin99b Szeryf (82,160 p.)

92,566 zapytań

141,420 odpowiedzi

319,615 komentarzy

61,952 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...