Go library for accessing the Keycloak API

keycloak

ci codeql Go Reference Go Report Card Total alerts

keycloak is a Go client library for accessing the Keycloak API.

Installation

go get github.com/zemirco/keycloak

Usage

package main

import (
    "context"

    "github.com/zemirco/keycloak"
    "golang.org/x/oauth2"
)

func main() {
    // create your oauth configuration
    config := oauth2.Config{
        ClientID: "admin-cli",
        Endpoint: oauth2.Endpoint{
            TokenURL: "http://localhost:8080/auth/realms/master/protocol/openid-connect/token",
        },
    }

    // get a valid token from keycloak
    ctx := context.Background()
    token, err := config.PasswordCredentialsToken(ctx, "admin", "admin")
    if err != nil {
        panic(err)
    }

    // create a new http client that uses the token on every request
    client := config.Client(ctx, token)

    // create a new keycloak instance and provide the http client
    k, err := keycloak.NewKeycloak(client, "http://localhost:8080/auth/")
    if err != nil {
        panic(err)
    }

    // start using the library and, for example, create a new realm
    realm := &keycloak.Realm{
        Enabled: keycloak.Bool(true),
        ID:      keycloak.String("myrealm"),
        Realm:   keycloak.String("myrealm"),
    }

    res, err := k.Realms.Create(ctx, realm)
    if err != nil {
        panic(err)
    }
}

Examples

Development

Use docker-compose to start Keycloak locally.

docker-compose up -d

Keycloak is running at http://localhost:8080/. The admin credentials are admin (username) and admin (password). If you want to change them simply edit the docker-compose.yml.

Keycloak uses PostgreSQL and all data is kept across restarts.

Use down if you want to stop the Keycloak server.

docker-compose down

Architecture

The main entry point is keycloak.go. This is where the Keycloak instance is created. It all starts in this file.

Within Keycloak we also have the concept of clients. They are the ones that connect to Keycloak for authentication and authorization purposes, e.g. our frontend and backend apps. That is why this library simply uses the keycloak instance of type Keycloak and not a client instance like go-github. Although technically this library is a Keycloak client library for Go. However this distinction should make it clear what is meant when we talk about a client in our context.

Testing

You need to have Keycloak running on your local machine to execute the tests. Simply use docker-compose to start it.

All tests are independent from each other. Before each test we create a realm and after each test we delete it. You don't have to worry about it since the helper function createRealm does that automatically for you. Inside this realm you can do whatever you want. You don't have to clean up after yourself since everything is deleted automatically when the realm is deleted.

Run all tests.

go test -race -v ./...

Create code coverage.

go test -v ./... -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html

We have also provided a simple Makefile that run both jobs automatically.

make

Open coverage.html with your browser.

Design goals

  1. Zero dependencies

    It's just the Go standard library.

    The only exception is go-querystring to easily handle query parameters.

  2. Idiomatic Go

    Modelled after go-github and go-jira.

  3. Keep authentication outside this library

    This is the major difference to most of the other Go Keycloak libraries.

    We leverage the brilliant oauth2 package to deal with authentication. We have provided multiple examples to show you the workflow. It basically means we do not provide any methods to call the /token endpoint.

  4. Return struct and HTTP response

    Whenever the Keycloak API returns JSON content you'll get a proper struct as well as the HTTP response.

    func (s *ClientsService) Get(ctx context.Context, realm, id string) (*Client, *http.Response, error)

Related work

License

MIT

Owner
Mirco Zeiss
IT Architect
Mirco Zeiss
Comments
  • add Users.GetByID + Update

    add Users.GetByID + Update

    Just adding missing functionality.

    I wasn't able to test, because on my M1 keycloak did not come to life with docker-compose. I tried with the bitnami image to no avail.

    I hope tests run through without issues 🙃

  • Missing service to add role to a Group

    Missing service to add role to a Group

    Hi @zemirco , I've added a couple of methods to add/remove mapping between groups and roles, and the test cases as well Feel free to integrate them whenever you want Thanks, Daniele

  • Missing service to add role to a Group

    Missing service to add role to a Group

    GroupsService is missing the API to manage the roles mapped to a given group. At least these two methods should be added: func (s *GroupsService) AddRealmRoles(ctx context.Context, realm, group *Group, roles []*Role) (*http.Response, error) func (s *GroupsService) RemoveRealmRoles(ctx context.Context, realm, group *Group, roles []*Role) (*http.Response, error)

  • Create attribute to user

    Create attribute to user

    Hi,

    How do I create attributes from the user

    	user := &keycloak.User{
    		Enabled:   keycloak.Bool(true),
    		Username:  keycloak.String(data.FullName),
    		Email:     keycloak.String(data.Email),
    		FirstName: keycloak.String(data.FirstName),
    		LastName:  keycloak.String(data.LastName),
    		Attributes: ???
    	}
    

    I include this block but not working

    	user := &keycloak.User{
    		Enabled:   keycloak.Bool(true),
    		Username:  keycloak.String(data.FullName),
    		Email:     keycloak.String(data.Email),
    		FirstName: keycloak.String(data.FirstName),
    		LastName:  keycloak.String(data.LastName),
    		Attributes: {"attribute01": "value01","attribute02": "value02" }
    	}
    

    What is the correct format to create attributes?

  • fix: module v2

    fix: module v2

    fix issue:

    github.com/zemirco/keycloak/[email protected]: go.mod has non-.../v2 module path "github.com/zemirco/keycloak" (and .../v2/go.mod does not exist) at revision v2.0.0
    
  • http client is not auto relogin after refresh_token expired.

    http client is not auto relogin after refresh_token expired.

    config := oauth2.Config{
    	ClientID:     enums.Env.KeycloakClientId,
    	ClientSecret: enums.Env.KeycloakClientSecret,
    	RedirectURL:  enums.Env.KeycloakRedirect,
    	Endpoint: oauth2.Endpoint{
    		TokenURL: fmt.Sprintf("%srealms/%s/protocol/openid-connect/token", enums.Env.KeycloakEndpoint, enums.Env.KeycloakRealm),
    	},
    }
    
    // get a valid token from keycloak
    ctx := context.Background()
    token, err := config.PasswordCredentialsToken(ctx, enums.Env.KeycloakAdmin, enums.Env.KeycloakPassword)
    if err != nil {
    	panic(err)
    }
    
    // create a new http client that uses the token on every request
    client := config.Client(ctx, token)
    
    // create a new keycloak instance and provide the http client
    clientKeycloak, err := keycloak.NewKeycloak(client, enums.Env.KeycloakEndpoint)
    

    clientKeycloak can't call api after refresh_token expired.

  • Get PasswordCredentialsToken with TOTP

    Get PasswordCredentialsToken with TOTP

    First of all this is a very great project.

    In order to get a valid token you have to pass in username and admin like the following code snippet

    // get a valid token from keycloak
        ctx := context.Background()
        token, err := config.PasswordCredentialsToken(ctx, "admin", "admin")
        if err != nil {
            panic(err)
        }
    

    Unfortunately, I can't pass a required OTP-Token, so that my two factor authentication works. Can I adjust the PasswordCredentialsToken or add a second method, that I am able to pass the OTP-Token? The following code snippet describes my idea in detail

    // get a valid token from keycloak
        ctx := context.Background()
        token, err := config.PasswordCredentialsToken(ctx, "admin", "admin", "123456")
        if err != nil {
            panic(err)
        }
    

    The result would be another line totp=<one time token> within the application/x-www-form-urlencoded body

A GoLang wrapper for Politics & War's API. Forego the hassle of accessing the API directly!

A GoLang wrapper for Politics & War's API. Forego the hassle of accessing the API directly!

Mar 5, 2022
Go library for accessing the Codeship API v2

Codeship API v2 Client for Go Codeship API v2 client for Go. Documentation https://godoc.org/github.com/codeship/codeship-go Usage go get -u github.co

Sep 27, 2022
Go library for accessing the GitHub API

go-github go-github is a Go client library for accessing the GitHub API v3. Currently, go-github requires Go version 1.9 or greater. go-github tracks

Dec 30, 2022
Package githubv4 is a client library for accessing GitHub GraphQL API v4 (https://developer.github.com/v4/).

githubv4 Package githubv4 is a client library for accessing GitHub GraphQL API v4 (https://docs.github.com/en/graphql). If you're looking for a client

Dec 26, 2022
May 25, 2021
NotionGo is a Go client library for accessing the Notion API v1.

NotionGo (WIP) NotionGo is a Go client library for accessing the Notion API v1. Installation NotionGo is compatible with modern Go releases in module

May 22, 2021
go-ftx go-ftx is a Go client library for accessing the FTX API

go-ftx go-ftx is a Go client library for accessing the FTX API

Nov 14, 2022
Go library for accessing the BlaBlaCar API

go-blablacar is a Go client library for accessing the BlaBlaCar API.

Nov 27, 2022
Go library for accessing trending repositories and developers at Github.
Go library for accessing trending repositories and developers at Github.

go-trending A package to retrieve trending repositories and developers from Github written in golang. This package were inspired by rochefort/git-tren

Dec 21, 2022
Go(lang) client library for accessing information of an Apache Mesos cluster.

megos Go(lang) client library for accessing an Apache Mesos cluster. Features Determine the Mesos leader Get the current state of every mesos node (ma

Sep 27, 2022
🤖🚀📦 A Discord Bot for accessing the cdnjs platform
🤖🚀📦 A Discord Bot for accessing the cdnjs platform

A bridge between https://cdnjs.com/api and Discord Big shoutout to Br1ght0ne for helping me with writing helpers.go/SplitIn

Aug 17, 2022
efsu is for accessing AWS EFS from your machine without a VPN

efsu: VPN-less access to AWS EFS efsu is for accessing AWS EFS from your machine without a VPN. It achieves this by deploying a Lambda function and sh

Mar 11, 2022
Simple-Weather-API - Simple weather api app created using golang and Open Weather API key
Simple-Weather-API - Simple weather api app created using golang and Open Weather API key

Simple Weather API Simple weather api app created using golang and Open Weather

Feb 6, 2022
go-whatsapp-rest-API is a Go library for the WhatsApp web which use Swagger as api interface

go-whatsapp-rest-API go-whatsapp-rest-API is a Go library for the WhatsApp web which use Swagger as api interface Multi-devices (MD) Support. This ver

Dec 15, 2022
Go client for the YNAB API. Unofficial. It covers 100% of the resources made available by the YNAB API.

YNAB API Go Library This is an UNOFFICIAL Go client for the YNAB API. It covers 100% of the resources made available by the YNAB API. Installation go

Oct 6, 2022
An API client for the Notion API implemented in Golang

An API client for the Notion API implemented in Golang

Dec 30, 2022
lambda-go-api-proxy makes it easy to port APIs written with Go frameworks such as Gin to AWS Lambda and Amazon API Gateway.

aws-lambda-go-api-proxy makes it easy to run Golang APIs written with frameworks such as Gin with AWS Lambda and Amazon API Gateway.

Jan 6, 2023
A API scanner written in GOLANG to scan files recursively and look for API keys and IDs.

GO FIND APIS _____ ____ ______ _____ _ _ _____ _____ _____ _____ / ____|/ __ \ | ____|_ _| \ | | __ \ /\ | __ \_

Oct 25, 2021
The NVD API is an unofficial Go wrapper around the NVD API.

NVD API The NVD API is an unofficial Go wrapper around the NVD API. Supports: CVE CPE How to use The following shows how to basically use the wrapper

Jan 7, 2023