| // Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // This file provides utilities for exchanging an OAuth token for a blessing via |
| // the Vanadium identity provider, and initializing a Vanadium context with this |
| // blessing. |
| // |
| // See v.io/x/ref/services/syncbase/bridge/mojo/blessings.go for more |
| // documentation. |
| |
| package bridge |
| |
| import ( |
| "encoding/base64" |
| "fmt" |
| "io/ioutil" |
| "net/http" |
| "net/url" |
| "strings" |
| |
| "v.io/v23" |
| "v.io/v23/context" |
| "v.io/v23/security" |
| "v.io/v23/vom" |
| seclib "v.io/x/ref/lib/security" |
| ) |
| |
| // SetBlessings exchanges an OAuth token for blessings from the dev.v.io server. |
| // Currently, oauthProvider must be set to "google". |
| func SetBlessings(ctx *context.T, oauthProvider string, oauthToken string) error { |
| if strings.ToLower(oauthProvider) != "google" { |
| return fmt.Errorf("unsupported oauthProvider %q; currently, \"google\" is the only supported provider", oauthProvider) |
| } |
| p := v23.GetPrincipal(ctx) |
| blessings, err := token2blessings(oauthToken, p.PublicKey()) |
| if err != nil { |
| return err |
| } |
| ctx.Infof("Obtained blessings %v", blessings) |
| if err := seclib.SetDefaultBlessings(p, blessings); err != nil { |
| return fmt.Errorf("failed to use blessings: %v", err) |
| } |
| return nil |
| } |
| |
| func token2blessings(token string, key security.PublicKey) (security.Blessings, error) { |
| var ret security.Blessings |
| url, err := token2blessingURL(token, key) |
| if err != nil { |
| return ret, err |
| } |
| |
| resp, err := http.Get(url) |
| if err != nil { |
| return ret, fmt.Errorf("HTTP request to exchange OAuth token for blessings failed: %v", err) |
| } |
| |
| defer resp.Body.Close() |
| b64bytes, err := ioutil.ReadAll(resp.Body) |
| |
| vombytes, err := base64.URLEncoding.DecodeString(string(b64bytes)) |
| if err != nil { |
| return ret, fmt.Errorf("invalid base64 encoded blessings: %v", err) |
| } |
| if err := vom.Decode(vombytes, &ret); err != nil { |
| return ret, fmt.Errorf("invalid encoded blessings: %v", err) |
| } |
| return ret, nil |
| } |
| |
| func token2blessingURL(token string, key security.PublicKey) (string, error) { |
| base, err := url.Parse("https://dev.v.io/auth/google/bless") |
| if err != nil { |
| return "", fmt.Errorf("failed to parse blessing URL: %v", err) |
| } |
| pub, err := key.MarshalBinary() |
| if err != nil { |
| return "", fmt.Errorf("invalid public key: %v", err) |
| } |
| |
| params := url.Values{} |
| params.Add("public_key", base64.URLEncoding.EncodeToString(pub)) |
| params.Add("token", token) |
| params.Add("output_format", "base64vom") |
| |
| base.RawQuery = params.Encode() |
| return base.String(), nil |
| } |