// authenticateUser will add the store expected Macaroon Authorization header for user func authenticateUser(r *http.Request, user *auth.UserState) { var buf bytes.Buffer fmt.Fprintf(&buf, `Macaroon root="%s"`, user.StoreMacaroon) // deserialize root macaroon (we need its signature to do the discharge binding) root, err := auth.MacaroonDeserialize(user.StoreMacaroon) if err != nil { logger.Debugf("cannot deserialize root macaroon: %v", err) return } for _, d := range user.StoreDischarges { // prepare discharge for request discharge, err := auth.MacaroonDeserialize(d) if err != nil { logger.Debugf("cannot deserialize discharge macaroon: %v", err) return } discharge.Bind(root.Signature()) serializedDischarge, err := auth.MacaroonSerialize(discharge) if err != nil { logger.Debugf("cannot re-serialize discharge macaroon: %v", err) return } fmt.Fprintf(&buf, `, discharge="%s"`, serializedDischarge) } r.Header.Set("Authorization", buf.String()) }
func (s *authSuite) TestMacaroonDeserializeInvalidData(c *C) { serialized := "invalid-macaroon-data" deserialized, err := auth.MacaroonDeserialize(serialized) c.Check(deserialized, IsNil) c.Check(err, NotNil) }
func (s *authSuite) TestMacaroonSerialize(c *C) { m, err := macaroon.New([]byte("secret"), "some-id", "location") c.Check(err, IsNil) serialized, err := auth.MacaroonSerialize(m) c.Check(err, IsNil) deserialized, err := auth.MacaroonDeserialize(serialized) c.Check(err, IsNil) c.Check(deserialized, DeepEquals, m) }
// refreshDischarges will request refreshed discharge macaroons for the user func refreshDischarges(user *auth.UserState) ([]string, error) { newDischarges := make([]string, len(user.StoreDischarges)) for i, d := range user.StoreDischarges { discharge, err := auth.MacaroonDeserialize(d) if err != nil { return nil, err } if discharge.Location() != UbuntuoneLocation { newDischarges[i] = d continue } refreshedDischarge, err := refreshDischargeMacaroon(d) if err != nil { return nil, err } newDischarges[i] = refreshedDischarge } return newDischarges, nil }
func (s *authSuite) TestMacaroonSerializeDeserializeStoreMacaroon(c *C) { // sample serialized macaroon using store server setup. serialized := `MDAxNmxvY2F0aW9uIGxvY2F0aW9uCjAwMTdpZGVudGlmaWVyIHNvbWUgaWQKMDAwZmNpZCBjYXZlYXQKMDAxOWNpZCAzcmQgcGFydHkgY2F2ZWF0CjAwNTF2aWQgcyvpXSVlMnj9wYw5b-WPCLjTnO_8lVzBrRr8tJfu9tOhPORbsEOFyBwPOM_YiiXJ_qh-Pp8HY0HsUueCUY4dxONLIxPWTdMzCjAwMTJjbCByZW1vdGUuY29tCjAwMmZzaWduYXR1cmUgcm_Gdz75wUCWF9KGXZQEANhwfvBcLNt9xXGfAmxurPMK` deserialized, err := auth.MacaroonDeserialize(serialized) c.Check(err, IsNil) // expected json serialization of the above macaroon jsonData := []byte(`{"caveats":[{"cid":"caveat"},{"cid":"3rd party caveat","vid":"cyvpXSVlMnj9wYw5b-WPCLjTnO_8lVzBrRr8tJfu9tOhPORbsEOFyBwPOM_YiiXJ_qh-Pp8HY0HsUueCUY4dxONLIxPWTdMz","cl":"remote.com"}],"location":"location","identifier":"some id","signature":"726fc6773ef9c1409617d2865d940400d8707ef05c2cdb7dc5719f026c6eacf3"}`) var expected macaroon.Macaroon err = expected.UnmarshalJSON(jsonData) c.Check(err, IsNil) c.Check(deserialized, DeepEquals, &expected) // reserializing the macaroon should give us the same original store serialization reserialized, err := auth.MacaroonSerialize(deserialized) c.Check(err, IsNil) c.Check(reserialized, Equals, serialized) }
// LoginUser logs user in the store and returns the authentication macaroons. func LoginUser(username, password, otp string) (string, string, error) { macaroon, err := requestStoreMacaroon() if err != nil { return "", "", err } deserializedMacaroon, err := auth.MacaroonDeserialize(macaroon) if err != nil { return "", "", err } // get SSO 3rd party caveat, and request discharge loginCaveat, err := loginCaveatID(deserializedMacaroon) if err != nil { return "", "", err } discharge, err := dischargeAuthCaveat(loginCaveat, username, password, otp) if err != nil { return "", "", err } return macaroon, discharge, nil }