diff --git a/api/auth.go b/api/auth.go
index 3ef075b..2c32f39 100644
--- a/api/auth.go
+++ b/api/auth.go
@@ -9,12 +9,6 @@ type AuthRegisterRequest struct {
 	LastName  string `json:"last_name,omitempty"`
 }
 
-// AuthLoginRequest is the definition of POST /v2/auth/login/.
-type AuthLoginRequest struct {
-	Username string `json:"username"`
-	Password string `json:"password"`
-}
-
 // AuthLoginResponse is the definition of /v2/auth/login/.
 type AuthLoginResponse tokenResponse
 
@@ -41,5 +35,6 @@ type AuthRegenerateResponse tokenResponse
 
 // A generic defenition of a token response.
 type tokenResponse struct {
-	Token string `json:"token"`
+	Token    string `json:"token"`
+	Username string `json:"username,omitempty"`
 }
diff --git a/auth/auth.go b/auth/auth.go
index d6b9301..25ce52e 100644
--- a/auth/auth.go
+++ b/auth/auth.go
@@ -3,9 +3,10 @@ package auth
 
 import (
 	"encoding/json"
-
+	"fmt"
 	drycc "github.com/drycc/controller-sdk-go"
 	"github.com/drycc/controller-sdk-go/api"
+	"net/http"
 )
 
 // Register a new user with the controller.
@@ -26,27 +27,35 @@ func Register(c *drycc.Client, username, password, email string) error {
 	return err
 }
 
-// Login to the controller and get a token
-func Login(c *drycc.Client, username, password string) (string, error) {
-	user := api.AuthLoginRequest{Username: username, Password: password}
-	reqBody, err := json.Marshal(user)
-
-	if err != nil {
-		return "", err
+// Login to the controller and get a oauth url
+func Login(c *drycc.Client) (string, error) {
+	c.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+		return http.ErrUseLastResponse
 	}
+	res, reqErr := c.Request("POST", "/v2/auth/login/", nil)
 
-	res, reqErr := c.Request("POST", "/v2/auth/login/", reqBody)
 	if reqErr != nil && !drycc.IsErrAPIMismatch(reqErr) {
 		return "", reqErr
 	}
 	defer res.Body.Close()
 
+	URL := res.Header.Get("Location")
+	return URL, reqErr
+}
+
+// Token to the controller and get a token
+func Token(c *drycc.Client, key string) (api.AuthLoginResponse, error) {
+	path := fmt.Sprintf("/v2/auth/token/%s/", key)
+	res, reqErr := c.Request("GET", path, nil)
+	if reqErr != nil && !drycc.IsErrAPIMismatch(reqErr) {
+		return api.AuthLoginResponse{}, reqErr
+	}
+	defer res.Body.Close()
 	token := api.AuthLoginResponse{}
-	if err = json.NewDecoder(res.Body).Decode(&token); err != nil {
-		return "", err
+	if err := json.NewDecoder(res.Body).Decode(&token); err != nil {
+		return api.AuthLoginResponse{}, err
 	}
-
-	return token.Token, reqErr
+	return token, reqErr
 }
 
 // Delete deletes a user.
diff --git a/auth/auth_test.go b/auth/auth_test.go
index 7d28c62..c7b48cc 100644
--- a/auth/auth_test.go
+++ b/auth/auth_test.go
@@ -2,6 +2,7 @@ package auth
 
 import (
 	"fmt"
+	"github.com/drycc/controller-sdk-go/api"
 	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
@@ -11,7 +12,6 @@ import (
 )
 
 const registerExpected string = `{"username":"test","password":"opensesame","email":"test@example.com"}`
-const loginExpected string = `{"username":"test","password":"opensesame"}`
 const passwdExpected string = `{"username":"test","password":"old","new_password":"new"}`
 const regenAllExpected string = `{"all":true}`
 const regenUserExpected string = `{"username":"test"}`
@@ -51,23 +51,15 @@ func (f *fakeHTTPServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
 	}
 
 	if req.URL.Path == "/v2/auth/login/" && req.Method == "POST" {
-		body, err := ioutil.ReadAll(req.Body)
-
-		if err != nil {
-			fmt.Println(err)
-			res.WriteHeader(http.StatusInternalServerError)
-			res.Write(nil)
-			return
-		}
-
-		if string(body) != loginExpected {
-			fmt.Printf("Expected '%s', Got '%s'\n", loginExpected, body)
-			res.WriteHeader(http.StatusInternalServerError)
-			res.Write(nil)
-			return
-		}
+		res.Header().Add("Location", "/v2/login/drycc/?key=fdbf3b34742e4ed2be4dfa848af13007/")
+		res.WriteHeader(http.StatusFound)
+		res.Write(nil)
+		return
+	}
 
-		res.Write([]byte(`{"token":"abc"}`))
+	if req.URL.Path == "/v2/auth/token/fdbf3b34742e4ed2be4dfa848af13007/" && req.Method == "GET" {
+		res.WriteHeader(http.StatusOK)
+		res.Write([]byte(`{"username":"test","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}`))
 		return
 	}
 
@@ -187,19 +179,45 @@ func TestLogin(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	actual, err := Login(drycc, "test", "opensesame")
+	actual, err := Login(drycc)
 
 	if err != nil {
 		t.Error(err)
 	}
 
-	expected := "abc"
-
+	expected := "/v2/login/drycc/?key=fdbf3b34742e4ed2be4dfa848af13007/"
 	if actual != expected {
 		t.Errorf("Expected %s, Got %s", expected, actual)
 	}
 }
 
+func TestToken(t *testing.T) {
+	t.Parallel()
+
+	handler := fakeHTTPServer{}
+	server := httptest.NewServer(&handler)
+	defer server.Close()
+
+	drycc, err := drycc.New(false, server.URL, "abc")
+	if err != nil {
+		t.Fatal(err)
+	}
+	expected := api.AuthLoginResponse{
+		Username: "test",
+		Token:    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
+	}
+
+	token, err := Token(drycc, "fdbf3b34742e4ed2be4dfa848af13007")
+
+	if err != nil {
+		t.Error(err)
+	}
+
+	if token != expected {
+		t.Errorf("Expected %s, Got %s", expected, token)
+	}
+}
+
 func TestPasswd(t *testing.T) {
 	t.Parallel()
 
