in lib/translator/dbgap.go [211:360]
func (s *DbGapTranslator) translateToken(ctx context.Context, token *oidc.IDToken, claims dbGapClaims, now time.Time) (*ga4gh.Identity, error) {
id := ga4gh.Identity{
Issuer: token.Issuer,
Subject: token.Subject,
Expiry: token.Expiry.Unix(),
GivenName: claims.Vcard.GivenName,
FamilyName: claims.Vcard.FamilyName,
Name: strutil.JoinNonEmpty([]string{claims.Vcard.GivenName, claims.Vcard.FamilyName}, " "),
Email: claims.Vcard.Email,
VisaJWTs: []string{},
}
for _, ident := range claims.Identity {
if ident.Authority == eraCommonsAuthority {
if username, ok := ident.ID.(string); ok {
id.Username = username
}
}
}
accessions := make(map[string]dbGapAccess)
type source struct {
orgID string
by string
}
affiliations := make(map[string]source)
for _, p := range claims.DbGapPassport {
for _, a := range p.Access {
if a.Study.Accession == nil {
continue
}
// TODO: Verify that the heuristics for de-duplicating access entries is correct.
ac := *a.Study.Accession
exp := a.Expires
if access, ok := accessions[ac]; ok {
// For duplicate accessions, only keep the one with the later expiry timestamp.
if access.Expires > exp {
continue
}
}
accessions[ac] = dbGapAccess{
Expires: exp,
Issued: a.Issued,
}
}
if p.Org == nil || len(*p.Org) == 0 || p.Role == nil || len(*p.Role) == 0 {
continue
}
var r string
if *p.Role == "pi" || *p.Role == "downloader" {
r = "nih.researcher"
} else {
r = "member"
}
o := removePunctuation.ReplaceAllString(*p.Org, "")
o = strings.ReplaceAll(o, " ", "-")
v := r + "@" + o + ".orgs.nih.gov"
// Does not deal with complex cases where multiple org_DUNS attest to the same
// "value" (v) for AffiliationAndRole.
if src, ok := affiliations[v]; !ok || src.by == "self" {
by := "so"
if p.SO == nil || *p.SO == "" {
by = "self"
}
affiliations[v] = source{
orgID: *p.OrgID,
by: by,
}
}
}
currUnixTime := now.Unix()
affiliationAsserted := now.Unix()
for a, val := range accessions {
visa := ga4gh.VisaData{
StdClaims: ga4gh.StdClaims{
Subject: token.Subject,
Issuer: s.visaIssuer,
ExpiresAt: val.Expires,
IssuedAt: val.Issued,
},
Assertion: ga4gh.Assertion{
Type: ga4gh.ControlledAccessGrants,
Value: ga4gh.Value("https://dac.nih.gov/datasets/" + a),
Source: dbGapIssuer,
By: ga4gh.DAC,
Asserted: affiliationAsserted,
},
Scope: visaScope,
}
v, err := ga4gh.NewVisaFromData(ctx, &visa, s.visaJKU, s.signer)
if err != nil {
return nil, fmt.Errorf("sign ControlledAccessGrants claim failed: %s", err)
}
id.VisaJWTs = append(id.VisaJWTs, string(v.JWT()))
// Keep the oldest Issued accession for use as affiliationAsserted.
if val.Issued > 0 && val.Issued < affiliationAsserted {
affiliationAsserted = val.Issued
}
}
for a, src := range affiliations {
// Claim for dbGap
visa := ga4gh.VisaData{
StdClaims: ga4gh.StdClaims{
Issuer: s.visaIssuer,
ExpiresAt: currUnixTime + validSec,
IssuedAt: affiliationAsserted,
},
Assertion: ga4gh.Assertion{
Type: ga4gh.AffiliationAndRole,
Value: ga4gh.Value(a),
Source: dbGapIssuer,
By: ga4gh.System,
Asserted: affiliationAsserted,
},
Scope: visaScope,
}
v, err := ga4gh.NewVisaFromData(ctx, &visa, s.visaJKU, s.signer)
if err != nil {
return nil, fmt.Errorf("sign dbGap ClaimAffiliationAndRole claim failed: %s", err)
}
id.VisaJWTs = append(id.VisaJWTs, string(v.JWT()))
// Claim for org
visa = ga4gh.VisaData{
StdClaims: ga4gh.StdClaims{
Issuer: s.visaIssuer,
ExpiresAt: currUnixTime + validSec,
IssuedAt: affiliationAsserted,
},
Assertion: ga4gh.Assertion{
Type: ga4gh.AffiliationAndRole,
Value: ga4gh.Value(a),
Source: ga4gh.Source(dbGapOrgURL + src.orgID),
By: ga4gh.By(src.by),
Asserted: affiliationAsserted,
},
Scope: visaScope,
}
v, err = ga4gh.NewVisaFromData(ctx, &visa, s.visaJKU, s.signer)
if err != nil {
return nil, fmt.Errorf("sign org ClaimAffiliationAndRole claim failed: %s", err)
}
id.VisaJWTs = append(id.VisaJWTs, string(v.JWT()))
}
return &id, nil
}