
Lesson Description
The "Authentication Middleware" Lesson is part of the full, Complete Go for Professional Developers course featured in this preview video. Here's what you'd learn in this lesson:
Melkey codes the Authenticate middleware function to act as a wrapper around other route handler functions requiring authentication. This wrapper function checks for an Authorization header in the request with a "Bearer" token. If an authorization header is not found, an anonymous user is added to the request. If the token is invalid, an error is thrown. - `
Transcript from the "Authentication Middleware" Lesson
[00:00:00]
>> Melkey: So now we have these two helper functions to modify, to inject the context and also to retrieve the value from the context. Let's go ahead and create a function so it's gonna be on user middleware, and this function is gonna be called authenticate, okay? And all this is gonna do this authenticate function is gonna be a wrapper on our existing http handler function.
[00:00:22]
So all those functions that we've declared in our routes.go.handle, getUserID, handleCreateWorkout, etc., etc., this is gonna wrap them, right? And the way this can work is when authenticate gets wrapped by a function, we want the next handler function to work right away. We want authenticate to do its thing, and then we want the next chain of http methods to be called right after that.
[00:00:48]
And so we can do this by writing next the call, http, what it's gonna accept is going to be HandlerFunc, okay, and it's going to respond with an http.Handler like so. And then here we can, right away, just return http.HandlerFunc, like this. It's gonna be anonymous function func, which is going to take w, http.ResponseWriter, which again, this is a signature of all those handler functions, http.Request like so.
[00:01:27]
And so now within here, within this anonymous function, we can interject any incoming requests to our server, right? Any incoming request that we wrap authenticate around, to be specific. So if you wrap them around all of them, we will have this interjecting every single call that we get, okay?
[00:01:58]
So with that, we can first start by adding a w.Header. I'm gonna add a vary and an authorization tag, so authorization like so. Here we can do authHeader, okay, and we can do r.Header.Get so it's gonna request or get all of the headers associated with authorization.
>> Melkey: Give ourselves some more room, okay?
[00:02:34]
And then we can check if it exists or not. So here, if authHeader is an empty string, right? So that means this request, there is no authorization attempt. We can do r, is gonna be SetUser, so we're gonna pass an r since it's the first argument that user expects.
[00:03:02]
And then we can do store.AnonymousUser like this. So now, because the caller here did not supply us with an authorization header, we know, or at least we can assume this is an anonymous, not logged in user. And so with that, we can just simply do next.ServeHTTP(w, r), so then it's going to go into the next function in the chain, and then we can return like so.
[00:03:31]
Otherwise we can start checking header parts is going to be strings.Split, okay, we're gonna pass in the authHeader. At this point, we assume that the authHeader is not an empty string, and it does, in fact, exist. I'm gonna split it on spacing here because, remember, it's going to be something like Bearer <TOKEN> or authorization TOKEN, right?
[00:03:59]
So this is gonna be the space between the string is what we're going to be after, what we're gonna be validating here. So here we split header parts into two equivalent pieces. So here we can do if len(headerParts) is not equal to 2, or headerParts at the 0th Index, okay, does not equal to something like Bearer.
[00:04:25]
>> Melkey: Okay, can do utils.WriteJSON, w, we can do http.StatusUnauthorized, utils.Envelope, we can say error.
>> Melkey: The invalid authorization header, like so and then we can return.
>> Melkey: And so with that, we know that the header part at the one, so the second part at the first index is actually the token.
[00:05:01]
So token would be headerParts, 1 like so, then user err. Now we can use that token to retrieve any sort of user. So we can use userMiddleware, UserStore, we can use that new function GetUserToken like so, we can put in the token itself. Let me just remind myself, yeah.
[00:05:28]
So this first argument is scope here, so we can do tokens.Scopeauth and then the token underneath, okay? We can check that err. So if err does not equal to nil. Here we can do utils.writeJSON w, http.StatusUnauthorized like so, utils.envelope. We can say error, all right, and we can say just invalid token.
[00:06:03]
>> Melkey: Okay, if user is nil, all right, we can do the same thing. So let's just go ahead and also add the return.
>> Melkey: We can say, if the user is no, can do StatusUnauthorized, and we can do error. Instead of invalid token, we can just say something like token expired or invalid.
[00:06:35]
>> Melkey: At the end, we can do r = SetUser r, and put in that user, you can do next.serveHTTP, (w, r) return.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops