Documentation ¶
Overview ¶
Package auth provides one possible authentication framework based on username and password. To use it, call RegisterAuthenticationService and pass it a structure that will handle the various routines for authentication.
On the client side, you send an auth operation to the auth endpoint by sending 2 form values:
- An "op" value, which is the operation to perform. See OpHello, etc. for possible values
- A "msg" value, which gets passed on the auth service you provide.
You coordinate between your client and your service on how to encode your messages. A common way would be to use json, but its up to you to do the encoding and decoding on either end.
See the AuthI interface for details on what each message type should accomplish.
This authentication system can be used to implement a token authorization flow, which is not the recommended way of doing authorization in apps, but is an acceptable way of doing it. It requires a client that can store cookies. The primary problem with this flow is that the client must gather that username and password, which can be problematic for mobile app clients since they must be very careful to not locally store the password accidentally.
Index ¶
Constants ¶
const ( OpHello = "hello" // Requires a session in order to create a new user. Helps us rate limit new user requests. OpNewUser = "new" OpLogin = "login" OpTokenLogin = "token" OpRevoke = "logout" OpRecover = "recover" // When passing this one, you will need to specify your own recovery method in the message. )
These are the operations accepted in the op form variable
Variables ¶
var ApiEndpoint = "/api/auth"
ApiEndpoint is the url for the authorization api. Feel free to change the default during startup.
var HackerDelay = 20 * time.Second
HackerDelay is the amount of time to delay a response if we detect a hacker. Feel free to change the default during startup.
var LoginRateLimit int64 = 3
LoginRateLimit is the number of seconds to permit between login attempts. Attempts to login faster than this will be rejected.
Functions ¶
func MakeAuthApiServer ¶
func MakeAuthApiServer(a app.ApplicationI) http.Handler
func RegisterAuthenticationService ¶
func RegisterAuthenticationService(a AuthI)
Types ¶
type AuthI ¶
type AuthI interface { // NewUser should create a new user in your database with credentials specified in the message. // The message comes from the "msg" form value sent by the client, so the client should put // whatever credentials are needed in that form value, and then you can extract the credentials on the server // end from the message. // If you are doing token based authentication, send back the token you have created and saved in your // database as well as a hash of the user's id. You can send it back in the // body of your response, or as a header. You should also save an identifier for the user in the session so that // the new user is also logged in. Return true if the attempt was successful, false if not. // One reason for an unsuccessful attempt might // be too short a user name, or an insecure password. Communicate that information in your response to the client. NewUser(ctx context.Context, message []byte, w http.ResponseWriter) bool // Login attempts to log in using the credentials in the message. // The message comes from the "msg" form value sent by the client, so the client should put // whatever credentials are needed in that form value, and then you can extract the credentials on the server // end from the message. // Return true if the login attempt was successful, and false if not. // If using tokens, return a saved token and a hash of your user id if login was successful. // Also, put the user id in the session. If login was not successful, return false, but also // write the reason to the writer so the client can know what happened, and also return an error code, // likely by returning a 401 response code in the header. Login(ctx context.Context, msg []byte, w http.ResponseWriter) bool // TokenLogin should attempt to log in using a token and id hash in the message. This would be a token that you have // previously returned in one of the above methods. Puts a user id in the session if successful. // Returns true if successful and false if not. TokenLogin(ctx context.Context, msg []byte, w http.ResponseWriter) bool // RevokeToken should revoke the token in the message. The session will be closed by the service as well. // You should delete the token from the database. RevokeToken(ctx context.Context, msg []byte, w http.ResponseWriter) bool // Recover should give the user information on how to reset the password. We do not immediately reset anything, // since this might come from a malicious attack. Only after the user has successfully completed the recovery // process should you remove all tokens associated with this user. You could potentially include in the msg // instructions on what recovery method to use. Write back instructions for the user on what to do next. Recover(ctx context.Context, msg []byte, w http.ResponseWriter) bool // WriteError should write the errorMessage to the response writer, together with the code. You should format // the message in whatever way your client expects to receive it. WriteError(ctx context.Context, errorMessage string, httpCode int, w http.ResponseWriter) }
AuthI describes the interface for the authorization service you should implement. Note that rate limiting and general hacker protection have already been done for you. The msg parameter below is the decoded json sent by the client, and that you can use for your own needs.