GoFr - An opinionated Go Framework (original) (raw)

HTTP Authentication

Authentication is a crucial aspect of web applications, controlling access to resources based on user roles or permissions. It is the process of verifying a user's identity to grant access to protected resources. It ensures that only authenticated users can perform actions or access data within an application.

GoFr offers various approaches to implement authorization.

Exempted Paths

By default, the authentication middleware exempts the following paths from authentication:

The health check endpoint /.well-known/health is exempted by default, but as it may contain sensitive information about the service and its dependencies, it is recommended to require authentication for it.

1. HTTP Basic Auth

Basic Authentication is a simple HTTP authentication scheme where the user's credentials (username and password) are transmitted in the request header in a Base64-encoded format.

Basic auth is the simplest way to authenticate your APIs. It's built on HTTP protocol authentication scheme. It involves sending the prefix Basic trailed by the Base64-encoded <username>:<password> within the standard Authorization header.

Basic Authentication in GoFr

GoFr offers two ways to implement basic authentication:

1. Predefined Credentials

Use EnableBasicAuth(username, password) to configure GoFr with pre-defined credentials.

func main() {
    app := gofr.New()

    app.EnableBasicAuth("admin", "secret_password") // Replace with your credentials

    app.GET("/protected-resource", func(c *gofr.Context) (any, error) {
        // Handle protected resource access
        return nil, nil
    })

    app.Run()
}

2. Custom Validation Function

Use EnableBasicAuthWithValidator(validationFunc) to implement your own validation logic for credentials. The validationFunc takes the username and password as arguments and returns true if valid, false otherwise.

func validateUser(c *container.Container, username, password string) bool {
    // Implement your credential validation logic here
    // This example uses hardcoded credentials for illustration only
    return username == "john" && password == "doe123"
}

func main() {
    app := gofr.New()

    app.EnableBasicAuthWithValidator(validateUser)

    app.GET("/secure-data", func(c *gofr.Context) (any, error) {
        // Handle access to secure data
        return nil, nil
    })

    app.Run()
}

Adding Basic Authentication to HTTP Services

This code snippet demonstrates how to add basic authentication to an HTTP service in GoFr and make a request with the appropriate Authorization header:

app.AddHTTPService("order", "https://localhost:2000",
    &service.Authentication{UserName: "abc", Password: "pass"},
)

2. API Keys Auth

API Key Authentication is an HTTP authentication scheme where a unique API key is included in the request header X-Api-Key for validation against a store of authorized keys.

Usage:

GoFr offers two ways to implement API Keys authentication.

1. Framework Default Validation

package main

func main() {
    // initialize gofr object
    app := gofr.New()

    app.EnableAPIKeyAuth("9221e451-451f-4cd6-a23d-2b2d3adea9cf", "0d98ecfe-4677-48aa-b463-d43505766915")

    app.GET("/customer", Customer)

    app.Run()
}

2. Custom Validation Function

package main

func apiKeyValidator(c *container.Container, apiKey string) bool {
    validKeys := []string{"f0e1dffd-0ff0-4ac8-92a3-22d44a1464e4", "d7e4b46e-5b04-47b2-836c-2c7c91250f40"}

    return slices.Contains(validKeys, apiKey)
}

func main() {
    // initialize gofr object
    app := gofr.New()

    app.EnableAPIKeyAuthWithValidator(apiKeyValidator)

    app.GET("/customer", Customer)

    app.Run()
}

Adding API-KEY Authentication to HTTP Services

This code snippet demonstrates how to add API Key authentication to an HTTP service in GoFr and make a request with the appropriate Authorization header:

app.AddHTTPService("http-server-using-redis", "http://localhost:8000", &service.APIKeyConfig{APIKey: "9221e451-451f-4cd6-a23d-2b2d3adea9cf"})

3. OAuth 2.0

OAuth 2.0 is the industry-standard protocol for authorization. It focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices.

It involves sending the prefix Bearer trailed by the encoded token within the standard Authorization header.

OAuth Authentication in GoFr

GoFr supports authenticating tokens encoded by algorithm RS256/384/512.

App level Authentication

Enable OAuth 2.0 with three-legged flow to authenticate requests. Use EnableOAuth(jwks-endpoint,refresh_interval, options ...jwt.ParserOption) to configure GoFr with pre-defined credentials.

Description

EnableOAuth configures OAuth authentication middleware for the application.

Parameters

Parameter Type Description
jwksEndpoint string URL of the JWKS endpoint used to retrieve signing keys for token verification.
refreshInterval int Interval (in seconds) at which the JWKS cache is refreshed.
options ...jwt.ParserOption Optional JWT claim validation configurations, such as issuer, audience, and expiration requirements.

Available JWT Claim Validations

Expiration (exp) Validation

If the exp claim is present, it is always validated to ensure the token has not expired. However, to make the exp claim mandatory in our JWT tokens, we can use:

jwt.WithExpirationRequired()

This ensures that every token must include the exp claim, making expiration validation a strict requirement.

Issued At (iat) Validation

If the iat claim is present, it is ensured that tokens are not accepted before their issuance time. No additional configuration is needed for this validation.

Not Before (nbf) Validation

If the nbf claim is present, it is always validated to ensure that a JWT is only valid after a certain time. No additional configuration is needed for this validation.

Audience (aud) Validation

Verifies that the token is intended for the expected audience.

jwt.WithAudience("https://api.example.com")

Subject (sub) Validation

Ensures the token is associated with the expected subject.

jwt.WithSubject("user@example.com")

Issuer (iss) Validation

Ensures the token is issued by a trusted authority.

jwt.WithIssuer("https://auth.example.com")

Example

func main() {
    app := gofr.New()

    app.EnableOAuth(
        "http://jwks-endpoint", 
        20,
        jwt.WithExpirationRequired(), // to enforce presence of exp claim in every token
        jwt.WithAudience("https://api.example.com"),
        jwt.WithIssuer("https://auth.example.com")
        )

    app.GET("/protected-resource", func(c *gofr.Context) (any, error) {
        // Handle protected resource access
        return nil, nil
    })

    app.Run()
}

Adding OAuth Authentication to HTTP Services

For server-to-server communication it follows two-legged OAuth, also known as "client credentials" flow, where the client application directly exchanges its own credentials (ClientID and ClientSecret) for an access token without involving any end-user interaction.

This code snippet demonstrates how two-legged OAuth authentication is added to an HTTP service in GoFr and make a request with the appropriate Authorization header:

app.AddHTTPService("orders", "http://localhost:9000",
    &service.OAuthConfig{   // Replace with your credentials
        ClientID:     "0iyeGcLYWudLGqZfD6HvOdZHZ5TlciAJ",
        ClientSecret: "GQXTY2f9186nUS3C9WWi7eJz8-iVEsxq7lKxdjfhOJbsEPPtEszL3AxFn8k_NAER",
        TokenURL:     "https://dev-zq6tvaxf3v7p0g7j.us.auth0.com/oauth/token",
        Scopes:       []string{"read:order"},
        EndpointParams: map[string][]string{
            "audience": {"https://dev-zq6tvaxf3v7p0g7j.us.auth0.com/api/v2/"},
    },
})