Coder Social home page Coder Social logo

go-u2fhost's Introduction

u2fhost

GoDoc CircleCI codecov

A library for using U2F USB devices from Go programs.

Who is this for

This library allows clients to interface with U2F USB devices to perform user authentication.

Because U2F is supported in most major browsers (either natively or by extensions), the only place I really foresee this being used (and why I wrote it in the first place) is to add U2F support to CLI apps.

Usage

Registration

To register with a new device, you will need to construct a RegistrationRequest.

request := &RegisterRequest{
	// The challenge is provided by the server
	Challenge: "randomstringprovidedbyserver",
	// "The facet should be provided by the client making the request
	Facet:	 "https://example.com",
	// "The AppId may be provided by the server or the client client making the request.
	AppId:	 "https://example.com",
}

Next, get a list of devices that you can attempt to register with.

allDevices := Devices()
// Filter only the devices that can be opened.
openDevices := []Device{}
for i, device := range devices {
	err := device.Open()
	if err == nil {
		openDevices = append(openDevices, devices[i])
		defer func(i int) {
			devices[i].Close()
		}(i)
	}
}

Once you have a slice of open devices, repeatedly call the Register function until the user activates a device, or you time out waiting for the user.

// Prompt the user to perform the registration request.
fmt.Println("\nTouch the U2F device you wish to register...")
var response RegisterResponse
var err error
timeout := time.After(time.Second * 25)
interval := time.NewTicker(time.Millisecond * 250)
defer interval.Stop()
for {
    select {
    case <-timeout:
		fmt.Println("Failed to get registration response after 25 seconds")
		break
    case <-interval:
		for _, device := range openDevices {
			response, err := device.Register(req)
			if err != nil {
				if _, ok := err.(TestOfUserPresenceRequiredError); ok {
					continue
				} else {
					// you should handle errors more gracefully than this
					panic(err)
				}
			} else {
				return response
			}
		}
    }
}

Once you have a registration response, send the results back to your server in the form it expects.

Authentication

To authenticate with a device, you will need to construct a AuthenticateRequest.

request := &AuthenticateRequest{
	// The challenge is provided by the server
	Challenge: "randomstringprovidedbytheserver",
	 // "The facet should be provided by the client making the request
	Facet:	 "https://example.com",
	// "The AppId may be provided by the server or the client client making the request.
	AppId:	 "https://example.com",
	// The KeyHandle is provided by the server
	KeyHandle: "keyhandleprovidedbytheserver",
}

Next, get a list of devices that you can attempt to authenticate with.

allDevices := Devices()
// Filter only the devices that can be opened.
openDevices := []Device{}
for i, device := range devices {
	err := device.Open()
	if err == nil {
		openDevices = append(openDevices, devices[i])
		defer func(i int) {
				devices[i].Close()
		}(i)
	}
}

Once you have a slice of open devices, repeatedly call the Authenticate function until the user activates a device, or you time out waiting for the user.

prompted := false
timeout := time.After(time.Second * 25)
interval := time.NewTicker(time.Millisecond * 250)
defer interval.Stop()
for {
    select {
	case <-timeout:
		fmt.Println("Failed to get authentication response after 25 seconds")
		break
	case <-interval.C:
		for _, device := range openDevices {
			response, err := device.Authenticate(req)
			if err == nil {
				return response
				log.Debugf("Got error from device, skipping: %s", err)
			} else if _, ok := err.(TestOfUserPresenceRequiredError); ok && !prompted {
				fmt.Println("\nTouch the flashing U2F device to authenticate...\n")
				prompted = true
			} else {
				fmt.Printf("Got status response %#x\n", err)
			}
		}
    }
}

Example

The cmd directory contains a sample CLI program that allows you to run the register and authenticate operations, providing all of the inputs that would normally be provided by the server via command line flags.

Known issues/FAQ

What platforms has this been tested on?

At the moment only Mac OS, however nothing in the go codebase is platform specific, and the hid library supports Mac, Windows, and Linux, so in theory it should work on all platforms.

There is a known issue that prevents HID devices from being identified on Linux, as the hid library does not expose the usage page. There is a known workaround for this (and an issue filed), so it is not something fundamentally wrong with this implementation, and should be resolved in the near future.

The interface seems too low level, why isn't it easier to use?

Mostly because I wasn't sure what a good high level API would look like, and opted to provide a more general purpose low level API.

That said, in the future I may add a high level API similar to the Javascript U2F API.

go-u2fhost's People

Contributors

marshallbrekka avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.