theme | _class | paginate | backgroundColor | backgroundImage | footer | headingDivider | marp | style |
---|---|---|---|---|---|---|---|---|
gaia |
lead |
true |
![width:300px](images/banner-transparent.png) |
1 |
true |
section {
font-size: 25px;
}
container {
height: 300px;
width: 100%;
display: block;
justify-content: right;
text-align: right;
}
header {
float: right;
}
a {
color: blue;
text-decoration: underline;
background-color: lightgrey;
font-size: 80%;
}
table {
font-size: 22px;
}
div.mermaid { all: unset; }
|
Adrian Hoff Postdoctoral Researcher ITU
- How do we manage users?
- Registration
- Logging in
- Managing accounts
- How do we not mess up security related issues, e.g., storing passwords?
- What about advanced security measures, e.g., confirmation emails and MFA?
-
- Who are you?
-
- What are you allowed to do / access?
- Authorization requires Authentication!
HTTP is a stateless protocol. By default, HTTP requests are independent messages that don't retain user values. Source: Session and state management in ASP.NET Core (microsoft.com)
A cookie (also known as a web cookie or browser cookie) is a small piece of data a server sends to a user's web browser. The browser may store cookies, create new cookies, modify existing ones, and send them back to the same server with later requests. Cookies enable web applications to store limited amounts of data and remember state information; by default the HTTP protocol is stateless.
Text and Image Source: Using HTTP cookies (mozilla.org)
- Open your browser and access
https://github.com/
- Log out if you are logged in (or open a private browser tab)
- Open the developer tools in your browser (probably by pressing
F12
) - Navigate to the tab "Network" and reload the page (
F5
) - Select the root HTTP request-response-pair (first in the list)
- Inspect the headers of both the request and the response: Do they contain cookies?
- In a separate tab, log into your Github account and access
https://github.com/
- Again inspect the HTTP headers and compare them with your logged-out results
- What additional cookie data is sent from your browser?
- What does Github prompt your browser to store?
- Again inspect the HTTP headers and compare them with your logged-out results
-
⚠️ In this case, we are responsible for very sensitive user data- Example technology: ASP.NET Core Identity
-
- We leave the responsibility over user data to a third party
- This means that, to some degree, we depend on that third party
- Different kinds of solutions exist
- login via external authentification service (e.g., Auth0)
- login via third party account (e.g., GitHub or Facebook)
- Open protocols exist, e.g., OAuth and OpenID
- We leave the responsibility over user data to a third party
- Storing passwords in the database
- must not be stored as cleartext
- how else??
- Providing advanced security features, e.g., Multi-Factor-Authentication (MFA)
- Enabling users to update their information
- ...
- All of this requires (a lot of) source code
- It is easy to introduce bugs and security flaws
⚠️ We should not implement our own authentication system from scratch!- It is a lot of work and it is ☠️ dangerous: mistakes can cause severe security disasters
... as an example challenge in user authentication - you do not want to implement this yourself!
- Storing passwords in cleartext is not smart
- Can be read by everyone with access to database (e.g., malicious engineer in a company)
-
Better: Passing them through a function that...
- calculates a derived value (a "hash"):
Unhackable123
->Pc9QceViJCRLTIX8HcN5
- is extremely hard to reverse (derived value cannot be converted back to password):
Pc9QceViJCRLTIX8HcN5
-> ???
- calculates a derived value (a "hash"):
-
Even better: obfuscating the hashes further by adding random noise to the password
- this is called "salting the hash" 🧂 - same passwords receive different hashes
If you want to learn more, you could start with these articles on hashing and adding salt to hashes!
-
Often simply referred to as "Identity" (don't be confused by online resources)
-
Out-of-the-box support for (most of) what we discovered in previous slides
-
Notion of users is integrated into ASP.NET
- requests receive an
HttpContext
containing information, i.a., on the user sending it - based on that, ASP.NET Core Identity provides a solution for authorization
- requests receive an
-
Identity + EF Core =❤️
- user information (name, email, password, ...) need to be stored in our database
- passwords must be hashed (with salt! 🧂)
- Identity provides us with a secure solution to achieve this
- user information (name, email, password, ...) need to be stored in our database
- Claims store data on who a user is
- Authentication
- Can be used to determine what the user is allowed to do
- Authorization
Image source: Andrew Lock ASP.NET Core in Action, Third Edition
Image source: Section 23 of Andrew Lock ASP.NET Core in Action, Third Edition Image source: Section 23 of Andrew Lock ASP.NET Core in Action, Third Edition- Create a new ASP.NET Core web app project:
dotnet new webapp -au Individual
- the argument
-au Individual
adds Identity to the project setup, including a lot of UI templates (which, unfortunately, are hidden from you!) - there are other options besides
Individual
, we discuss those later
- the argument
- Inspect the generated project:
- The general structure should look familiar
- Have a look at the
Areas
folder- this is a special folder with special semantics!
- Have a look at the
Data
folder- the template comes with a default db context, a migration is already created
- note that the db context inherits from
IdentityDbContext
, providing functionality
- Have a look at the
Pages
folder, look intoPages/Shared/_LoginPartial.cshtml
- Run the project and play around with the launched website.
- create a user
- note that, per default, Identity is configured with email confirmation
- the part of sending an email needs to be implemented manually (not now)
- note that, per default, Identity is configured with email confirmation
- log into the website
- inspect your user data and how to change information, e.g., email or password
- create a user
-
Note that these authentication features all work out of the box!
-
Open the app's SQLite database with an SQLite analysis tool, e.g., DB Browser for SQLite
- the
ASPNetUsers
table is generated by Identity and contains data for registered users - inspect the
ASPNetUsers
table:- are the passwords hashed?
- the
Follow the instructions in the book: Chapter 23
General tipps:
- use the example project from earlier for orientation
- the
Microsoft.AspNetCore.Identity.UI
package adds a lot of razor pages to your application- however, these won't show in your folder structure
- once again, Microsoft is trying to hide complexity
- you can use "scaffolding" to override hidden pages with custom content where needed
- the book provides very useful tips here!
- however, these won't show in your folder structure
Utilize Identity by re-using their IdentityUser
class. Change your current domain model...
... to inherit from IdentityUser
:
Similarly, your DBContext
requires adaption (cf. book):
public class ChirpDbContext : IdentityDbContext<Author, IdentityRole<int>, int> { ... }
-
- full-blown (usually paid) service that takes care of authentication (e.g., Auth0)
- can be seamlessly integrated into an application
-
- authorize users through their user accounts with other services, e.g., Google, GitHub, Facebook, Apple, etc.
-
- a plathora of protocols exist
- notable open standards are OAuth and OpenID
OAuth (short for open authori-zation) is an open standard for access delegation, commonly used as a way for internet users to grant websites or applications access to their information on other websites but without giving them the passwords.
In our Chirp! project, actor roles are:
- Resource Owner = User (Chirp! and GH)
- User Agent = their browser
- Client = Chirp!
- Authorization Server = GitHub
- Resource Server (not used) = GitHub
Image source: J. Richer et al. OAuth2 in Action
- Chirp > User: "To authenticate, go here"
- Chirp > User: "To authenticate, go here"
- User > GitHub: "Hey, it's me!"
- User & GitHub: "Allow this app?" - "Yes!"
- GitHub > User: "Go here with this code"
- Chirp > User: "To authenticate, go here"
- User > GitHub: "Hey, it's me!"
- User & GitHub: "Allow this app?" - "Yes!"
- GitHub > User: "Go here with this code"
- User > Chirp: "Here I am, use this code"
- Chirp > GitHub:
- "The user authorized me!"
- "I am the real Chirp!" (client secret)
- Chirp > User: "To authenticate, go here"
- User > GitHub: "Hey, it's me!"
- User & GitHub: "Allow this app?" - "Yes!"
- GitHub > User: "Go here with this code"
- User > Chirp: "Here I am, use this code"
- Chirp > GitHub:
- "The user authorized me!"
- "I am the real Chirp!" (client secret)
- GitHub > Chirp: "Here is your token"
- Chirp > GitHub: "Give me this resource, here is my access token"
Oh my, this looks complicated! Do I have to implement this myself??
There exist NuGeT packages for ASP.NET Core Identity for many services. Among these: GitHub!
Repository: AspNet.Security.OAuth.GitHub
- Go to github.com
- Click on your profile picture (upper right corner)
- Go to Settings
- In the left-hand side panel, go to Developer Settings
- Go to OAuth Apps
- Create a new App for your Chirp! application
- What is the "Authorization callback URL"?
- Look for it in the OAuth dance diagram shown on the previous slides
- What should you fill in here?
The shown configuration works for:
- local setup (in development)
- HTTPS
- port 5000
GitHub provides you with a Client ID and Client secret for your Chirp! app. You use these to configure the authentication:
builder.Services
.AddAuthentication(options =>
{
options.RequireAuthenticatedSignIn = true;
})
.AddGitHub(options =>
{
options.ClientId = githubClientId; // GitHub Client ID
options.ClientSecret = githubClientSecret; // GitHub Client secret
});
Microsoft developed a minimalistic tool for storing secrets FOR DEVELOPMENT outside the repository environment, so that these are accessible as if defined in appsettings.json
(where secrets will NEVER be included because that file is checked into Git!)
- Initialize the tool (from within project folder):
dotnet user-secrets init
- Inspect the resp.
.csproj
file. There should be a new tag<UserSecretsId>8g5s...</>
- The tool will create a file
~/.microsoft/usersecrets/8g5s.../secrets.json
- The file is empty right now, we can fill it with secrets
- Inspect the resp.
- Enter your GitHub Client ID and Client secret
dotnet user-secrets set "GitHub:ClientID" "TWTt8z9RhTQjGa7jpL1q"
dotnet user-secrets set "GitHub:ClientSecret" "ibep0j74ddatc3fdrpbtm627zhulvjmvgjsln6gx"
- Again inspect the secret file
~/.microsoft/usersecrets/8g5s.../secrets.json
and see if the entries were added - Note that the secret is stored in cleartext on your harddrive!
- Again inspect the secret file
Of course, you should test your Identity setup. Example: Checking whether clients get redirected when trying to access a protected resource
// Arrange
HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClientHandler.AllowAutoRedirect = false; // prevent redirects
client = new HttpClient(httpClientHandler);
// ... configuring the client and starting the server omitted
// Act
HttpResponseMessage resp = await client.GetAsync("/ProtectedPage");
string content = await resp.Content.ReadAsStringAsync();
// Assert
Assert.Equal(HttpStatusCode.Redirect, resp.StatusCode);
Assert.StartsWith("https://localhost/Identity/Account/Login", resp.Headers.Location.OriginalString);
Read more: https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-7.0
-
- Are carried from request to request to authenticate user
- Do never contain sensitive data as they are stored in cleartext and can be read freely
- Instead, services use cryptic session ids that are mapped to user sessions in backend
-
- ASP.NET Core Identity provides a secure foundation for implementing this
- However, we (server owners) are responsible for sensitive user data
-
- OAuth is an open standard for handling user authentication and access to resources without sharing passwords between services
- This is great, because we do not have responsibility over sensitity data
-
If not done, complete the Tasks (blue slides) from this class
-
Check the reading material
-
Work on the project
-
If you feel you want prepare for next session, read chapters 16, 17, and 18 in Andrew Lock ASP.NET Core in Action, Third Edition