Commit 3b5df52c authored by Pavel Borzenkov's avatar Pavel Borzenkov

connector/linkedin: implement RefreshConnector interface

Do Refresh() by querying user's profile data.

Since LinkedIn doesn't provide refresh tokens at all, and the access
tokens have 60 days expiration, refresh tokens issued by Dex will fail
to update after 60 days.
Signed-off-by: 's avatarPavel Borzenkov <pavel.borzenkov@gmail.com>
parent ab061194
......@@ -45,15 +45,20 @@ func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector
}, nil
}
type connectorData struct {
AccessToken string `json:"accessToken"`
}
type linkedInConnector struct {
oauth2Config *oauth2.Config
logger logrus.FieldLogger
}
// LinkedIn doesn't provide refresh tokens, so we don't implement
// RefreshConnector here.
// LinkedIn doesn't provide refresh tokens, so refresh tokens issued by Dex
// will expire in 60 days (default LinkedIn token lifetime).
var (
_ connector.CallbackConnector = (*linkedInConnector)(nil)
_ connector.RefreshConnector = (*linkedInConnector)(nil)
)
// LoginURL returns an access token request URL
......@@ -92,9 +97,40 @@ func (c *linkedInConnector) HandleCallback(s connector.Scopes, r *http.Request)
EmailVerified: true,
}
if s.OfflineAccess {
data := connectorData{AccessToken: token.AccessToken}
connData, err := json.Marshal(data)
if err != nil {
return identity, fmt.Errorf("linkedin: marshal connector data: %v", err)
}
identity.ConnectorData = connData
}
return identity, nil
}
func (c *linkedInConnector) Refresh(ctx context.Context, s connector.Scopes, ident connector.Identity) (connector.Identity, error) {
if len(ident.ConnectorData) == 0 {
return ident, fmt.Errorf("linkedin: no upstream access token found")
}
var data connectorData
if err := json.Unmarshal(ident.ConnectorData, &data); err != nil {
return ident, fmt.Errorf("linkedin: unmarshal access token: %v", err)
}
client := c.oauth2Config.Client(ctx, &oauth2.Token{AccessToken: data.AccessToken})
profile, err := c.profile(ctx, client)
if err != nil {
return ident, fmt.Errorf("linkedin: get profile: %v", err)
}
ident.Username = profile.fullname()
ident.Email = profile.Email
return ident, nil
}
type profile struct {
ID string `json:"id"`
FirstName string `json:"firstName"`
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment