Update 'Home'

master
Claire 2 years ago
parent
commit
e0d2cfa8b1
  1. 22
      Home.md

22
Home.md

@ -6,7 +6,9 @@ I'm not a fan of third-party dependencies. When I was working on this project in
If you want to understand how OAuth2 works in technical terms, this project lays everything out pretty clearly. The rest of this article is a copy of the code breakdown I wrote on my old WordPress site back in 2013.
## Step-by-Step Authentication Process
## Getting Started
### Step-by-Step Authentication Process
First off, let's look at what exactly we need to do with our code to allow logging in to Google and, more importantly, verifying that the login information is valid and that the login session from Google hasn't been compromised or tampered with.
1. Send the user to Google's login service via URL
@ -20,7 +22,7 @@ Okay...so maybe it's not quite that simple. On the other hand, it's also not as
The first step is the easiest, so we're going to cover that to get started.
## Sending the user to Google's login service
### Sending the user to Google's login service
In order for your application to use Google's OAuth2 service, there's a few things you need to do first.
Before you do anything, set up a Google account for your application. You can use an existing Google account, but I opted to create an account using an email under my new project's domain in order to keep this project separate from my personal online identity. Once that's done, log in to [Google Cloud's credentials console](https://console.cloud.google.com/apis/credentials). Create a new **OAuth client ID**. Follow the instructions to create a new application - it's pretty straightforward, but if you need more information, check out [Google's support article](https://support.google.com/cloud/answer/6158849). You're going to need to note down two important pieces of information provided by the API Console: your **client ID** and your **client secret**. Your client id is a unique identifier that tells Google what API project is being used. This doesn't change. It's also publicly visible in the login URL that your user will see in their browser's address bar during the login process.
@ -58,7 +60,9 @@ https://accounts.google.com/o/oauth2/auth?client_id=...&state=<%=Session["state"
When the user clicks this URL, it will direct them to either login to Google (if they're not already logged in) or authorize your application to use their credentials and information. As soon as the user tells Google it's okay for your application to use their information, they'll be taken back to whatever URI is in the `redirect_uri` section of the above URL. From there, we're going to do steps two and three - process the data and verify its integrity.
## Verifying the initial Google response
## Logging In
### Verifying the initial Google response
When the user clicks your login button or link and authorizes your application, Google will redirect the user back to your site. The redirect URL contains querystring data that can be used to verify the login session and access Google's APIs. The two querystring elements we are concerned with are state and code. When Google redirects back to your site, state will contain the value you passed through your original login link. If you followed my last piece in this series, this value will be the GUID generated when your login page originally loaded. This should still be present in your user's session in your application. The other value, code, is a one-time authorization code provided by Google. This is what you'll use to actually get your user's information from Google's authentication service. First, in the code for the login page (login.aspx in this example), I'm going to set all the variables for the request to be sent to Google's API.
```csharp
@ -280,7 +284,9 @@ At this point, you can use the decoded JSON array to add your user's information
This isn't a simple process, as you can see. However, once the process is clearly detailed, it's a lot easier to understand.
## Another brief interlude
## Validating Integrity
### Another brief interlude
Here's the thing. Google makes it clear in their ["Using OAuth2" guide](https://developers.google.com/identity/protocols/oauth2) that there are serious security implications with accessing a user's Google account information, and if you don't know what you're doing and don't take the appropriate security measures, you could accidentally make it really easy for anyone - including someone from 4chan - to pose as one of your users.
This isn't an exaggeration. When I was originally trying to figure out how to handle this whole OAuth2 beast for my project, every article I found about it either used DotNetOpenAuth or did nothing to verify the integrity of the user's data. The first step we took to mitigate this was to use a unique session ID that was passed to Google, passed back to our application, and checked against the ID in the user's web session.
@ -301,7 +307,7 @@ string[] tokenArray = gli.id_token.Split(new Char[] { '.' });
We've already dealt with the payloa. What we care about are the header and the signature, which are stored in `tokenArray[0]` and `tokenArray[2]`.
## Parsing the JWT Header
### Parsing the JWT Header
The header is a plaintext, Base64-encoded JSON array. I can't seem to find the page in Google's documentation that explains what the elements of this array are, but it's pretty easy, since there's only two: `alg` indicates what hashing algorithm was used for the signature in the third segment of the JWT, and `kid` gives us the ID of the Google public certificate that is paired with the private key Google used to sign the hash.
Just like how we handled the payload, we're going to make a class containing these elements...
@ -390,7 +396,7 @@ For anyone concerned about bandwidth - this function only goes out to the Intern
Now that we have our certificate, we can take a look at the third segment of the JWT - the signature - and use the certificate and the signature to validate our data.
## Validating the JWT digital signature
### Validating the JWT digital signature
First, we're going to create a `bool` that returns true if the signature is valid or false if the validation fails. This function is going to take both the key ID and the original JWT provided by Google, and will use the `verifySignature` function we just created.
```csharp
@ -476,7 +482,7 @@ byte[] data = Encoding.UTF8.GetBytes(toVerify);
And just like that, we're done with step one!
## Verifying the signature using RSA PKCS#1
### Verifying the signature using RSA PKCS#1
I have a confession to make. I spent a long time - several days, in fact - trying to use various bits of .NET's RSA libraries to do the actual signature validation. I got more than a little frustrated and probably cursed at least twice at my laptop.
Then, a messenger from above came to me in a dream and gave me everything I needed to know. Seriously.
@ -557,7 +563,7 @@ if (verifySignature(glh.kid, tokenArray))
Obviously, this doesn't do anything to add the user to our application's local database. I haven't gotten that far. At this point, however, we've taken all the measures necessary to verify the integrity of a user's Google account information and have assurance that the user is who they say they are.
## The big conclusion
### The big conclusion
Google's caution against using custom code is not without reason. Most web developers aren't going to understand enough about cryptography to know what needs to be done to ensure end-to-end integrity when using a third-party service for logging in. I had the distinct advantage of knowing a cryptography and security professional who was able to go through all the documentation with me and explain what each security term meant and what I needed to figure out how to do it in C#.
If you're still not comfortable with using your own code like this, that's okay - there's nothing wrong with using third party libraries. You just want to make sure you're using a library that is well-supported and well-maintained, because information security and cryptography are always evolving and changing as new threats and innovations are brought to the table.

Loading…
Cancel
Save