Skip to content

Upgrade process from 3.1.6 to 4.0

Jose edited this page Mar 6, 2019 · 13 revisions

Note: This is a draft doc. It's not complete neither accurate

These doc describes the steps to mutate a passport 3.1.6 into a 4.0 one:

Stop passport

Generate idp-initiated client

As per https://github.com/GluuFederation/community-edition-setup/tree/master/templates/passport.ldif#L1-L12

Upgrade /etc/gluu/conf/passport-config.json

Previous (3.1.x) property Becomes in 4.x
passportConfigAPI configurationEndpoint
applicationStartpoint failureRedirectUrl

The following remain the same: logLevel, clientId, keyPath, keyId, keyAlg

Some properties of 3.1.x file were moved to LDAP. See conf below

As an example, this is how passport-config.json looks now:

{
	"configurationEndpoint": "https://my.gluu.host/identity/restv1/passport/config",
	"failureRedirectUrl": "https://my.gluu.host/oxauth/auth/passport/passportlogin.htm",
	"logLevel": "debug",
	"clientId": "@!D709.DD63.C2A5.9C6A!0001!2533.B35B!0008!B37C.2DF3",
	"keyPath": "/etc/certs/passport-rp.pem",
	"keyId": "890dc947-f5ab-476a-bba2-4ae8f297672d",
	"keyAlg": "RS512"
}

Generate passport-central-config.json

The contents will end up imported under ou=oxpassport,ou=configuration,inum=...,ou=appliances,o=gluu (attribute gluuPassportConfiguration)

For reference, this is how a typical content looks like.

So based on the template, generate the 3 sections:

conf

For the logging section, use for level and consoleLogOnly the values already in passport-config.json (3.1.x)

For activeMQConf section, use the same values found under activeMQConf in passport-config.json (3.1.x), except for:

  • port: This is expected to be an integer (not a string as in 3.1.x). If conversion fails, simply set it to zero
  • isEnabled which is now simply called enabled for 4.x

idpInitiated

For every key (section) found in passport-inbound-idp-initiated.json create an item inside authorizationParams filling values as follows:

Property Value
provider The key value (e.g. "your_idp_name")
redirect_uri redirect_uri value
response_type response_type value
scope take scope value (it's an array) and convert it in a space-separated string

Account that if in passport-inbound-idp-initiated.json any of client_id or redirect_uri is empty, then the item in authorizationParams should not be created.

For clientId (in openidclient section) of passport-central-config.json, use the client_id of the first occurrence of openidclient found passport-inbound-idp-initiated.json. However, if this value is empty, use the inum of the idp-initiated client generated at the beginning.

Examples:

  1. If passport-inbound-idp-initiated.json is [this] (the default one), then the resulting idpInitiated section should look like:

    {
        "openidclient": {
            "authorizationEndpoint": "https://my.gluu.host/oxauth/restv1/authorize",
            "clientId": "@!....",
            "acrValues": "passport_saml"
        },
        "authorizationParams": []
    }
    
  2. If passport-inbound-idp-initiated.json is

    {
        "your_idp_name_1": {
            "openidclient": {
                "server_uri": "something",
                "client_id": "client_id_1"
            },
            "authorization_params": {
                "client_id": "client_id_1A",
                "redirect_uri": "redirect_uri_1",
                "acr_values": "acr1",
                "response_type": "code",
                "scope": ["openid", "user_name", "email"]
            }
        },
        "your_idp_name_2": {
            "openidclient": {
                "server_uri": "something2",
                "client_id": "client_id_2"
            },
            "authorization_params": {
                "client_id": "client_id_2A",
                "redirect_uri": "redirect_uri_2",
                "acr_values": "acr2",
                "response_type": "code token",
                "scope": ["openid"]
            }
        }
    }
    

    the result should be:

    {
        "openidclient": {
            "authorizationEndpoint": "https://my.gluu.host/oxauth/restv1/authorize",
            "clientId": "client_id_1",
            "acrValues": "passport_saml"
        },
        "authorizationParams": [
            {
                "provider" : "your_idp_name_1",
                "redirect_uri": "redirect_uri_1",
                "response_type": "code",
                "scope": "openid user_name email"
            },
            {
                "provider" : "your_idp_name_2",
                "redirect_uri": "redirect_uri_2",
                "response_type": "code token",
                "scope": "openid"
            }
        ]
    }
    

providers

In 3.1.x the providers information is found in 2 places: LDAP and passport-saml-config.json. LDAP has info about oauth-based providers, while the file has info about SAML providers.

oauth providers

For every attribute gluuPassportConfiguration under ou=oxpassport,ou=configuration,inum=...,ou=appliances,o=gluu create an item inside providers the following way:

Property Value
id Use the value of strategy field
displayName Use the value of strategy field
type Use "oauth" if strategy is any of dropbox, facebook, github, google, linkedin, openidconnect, tumblr, twitter, windowslive, yahoo. Otherwise use "openidconnect"
mapping Use the value of strategy field if strategy is any of dropbox, facebook, github, google, linkedin, openidconnect, tumblr, twitter, windowslive, yahoo. Otherwise use "openidconnect-default"
enabled use true
logoImg Lookup value2 where value1 is "logo_img" inside fieldset. If not found, do not set this property
requestForEmail Lookup value2 where value1 is "requestForEmail" inside fieldset. If it equals the string "true", use true (as boolean). Otherwise, do not set this property
emailLinkingSafe Lookup value2 where value1 is "emailLinkingSafe" inside fieldset. . If it equals the string "true", use true (as boolean). Otherwise, do not set this property

Fill property passportStrategyId according to the following rules:

mapping value Value for passportStrategyId
github passport-github
openidconnect-default passport-openidconnect
twitter passport-twitter
yahoo passport-yahoo-oauth2
tumblr passport-tumblr
linkedin passport-linkedin-oauth2
google passport-google-oauth2
facebook passport-facebook
dropbox passport-dropbox-oauth2
windowslive passport-windowslive

Fill a dictionary named "options" the following way: for every field (in fieldset) use value1 for the key and value2 for value. Ignore fields when value1 is any of logo_img, requestForEmail, emailLinkingSafe.

Example. Suppose the following is in LDAP:

gluuPassportConfiguration: {"strategy": "myOP", "fieldset": [{"value1": "logo_img", "value2": "some_url"}, {"value1": "requestForEmail", "value2": "true"}, {"value1": "extraPropertyA", "value2": "AHA"}, {"value1": "extraPropertyB", "value2": "WTF"}]}

gluuPassportConfiguration: {"strategy": "google", "fieldset": [{"value1": "logo_img", "value2" : "img/gugol.png"}, {"value1": "clientID", "value2": "some_client_id"}, {"value1": "clientSecret", "value2": "some_client_secret"}]}

gluuPassportConfiguration: {"strategy": "github", "fieldset": [{"value1": "someProperty", "value2" : "Nothing"}]}

This should generate:

[
        {
            "id": "myOP",
            "displayName": "myOP",
            "type": "openidconnect",
            "mapping" : "openidconnect-default",
            "enabled": true,
            "logo_img" : "some_url",
            "requestForEmail": true,
            "passportStrategyId": "passport-openidconnect",
            "options": {
                "extraPropertyA": "AHA",
                "extraPropertyB": "WTF"
            }
        },
        {
            "id": "google",
            "displayName": "google",
            "type": "oauth",
            "mapping" : "google",
            "enabled": true,
            "logo_img" : "img/gugol.png",
            "passportStrategyId": "passport-google-oauth2",
            "options": {
                "clientID": "some_client_id",
                "clientSecret": "some_client_secret"
            }
        },
        {
            "id": "github",
            "displayName": "github",
            "type": "oauth",
            "mapping" : "github",
            "enabled": true,
            "passportStrategyId": "passport-github",
            "options": {
                "someProperty": "someProperty"
            }
        }
]

saml providers

Besides the oauth providers, we also have to add the SAML ones to the providers array.

So for every key in passport-saml-config.json we have to create an item this way:

Property Value
id Use key
displayName Use key
type Use "saml"
enabled Use propery enable from json file. Convert it to boolean
logo_img As seen in logo_img property of json file
requestForEmail As seen in requestForEmail property of json file. If not present, do not set this property
emailLinkingSafe As seen in emailLinkingSafe property of json file. If not present, do not set this property
passportStrategyId Use "passport-saml"
mapping Use key

Fill a dictionary named "options" with all the subkeys present and their corresponding values except for reverseMapping, enable, logo_img, requestForEmail and emailLinkingSafe. All dictionary values must be stored as strings regardless of how they appear in the original passport-saml-config.json file.

Create a .js file under ~/temp/mappings with the name of the key. For instance, if the key is "My_Provider", a "My_Provider.js" can be created. Files created will be moved to its final destination afterwards

For generating the file use this template:

module.exports = profile => {
	return {
		local_key_0: profile["remote_key_val_0"],
		...
		local_key_n: profile["reverse_value_n"]
	}
}

Where local_key_i is the item at position i in generic_local_attributes_list and remote_key_val_i is the value of the j-th key in reverseMapping so that such key has the same name than the i-th element in generic_remote_attributes_list.

Remarks:

  • Both generic_remote_attributes_list and generic_local_attributes_list are comma-separated lists found in the configuration properties of the passport-saml script.
  • Both lists have the same length.
  • If for a value i, the i-th element of generic_remote_attributes_list is "provider", ignore and continue with the next value of i.
  • If there is no match in the reverseMapping with respect to generic_remote_attributes_list, ignore and continue with the next value of i.

The above is better explained using an example. Assume the following parameterization of passport_saml script:

...
oxConfigurationProperty: {"value1":"generic_remote_attributes_list","value2":"username, email, name, name, givenName, familyName, provider}
oxConfigurationProperty: {"value1":"generic_local_attributes_list" ,"value2":"uid, mail, cn, displayName, givenName, sn, provider"}
...

And assume the reverseMapping in passport-saml-config has the following:

{
      "email": "email",
      "username": "urn:oid:0.9.2342.19200300.100.1.1",
      "id": "urn:oid:0.9.2342.19200300.100.1.1",
      "name": "urn:oid:2.5.4.42",
      "givenName": "urn:oid:2.5.4.42",
      "provider": "issuer"
}

local_key_0 is uid (the first element in the "local" list). To compute remote_key_val_0, we pick the 0-th element in "remote", that is, username and then search for it in the reverseMapping. The following is found "username": "urn:oid:0.9.2342.19200300.100.1.1" so the value needed is "urn:oid:0.9.2342.19200300.100.1.1" yielding:

uid: profile["urn:oid:0.9.2342.19200300.100.1.1"]

Following the same idea, for local_key_1 (mail), "email" is searched in the reverse mapping, thus yielding:

mail: profile["email"],

Note that local_key_5 is not generated since familyName is not part of reverse mapping. local_key_6 is not generated since the 6th key in the remote list is "provider".

Example with saml providers

Here it goes an example that sums up all of the previous section. Assume passport-saml-config.json has:

{
  "your_idp_name1": {
    "entryPoint": "https://idp1.example.com/idp/profile/SAML2/POST/SSO",
    "issuer": "urn:test:example",
    "identifierFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
    "enable": "true",
    "cert": "your_idp_public_certicate_in_single_line",
    "reverseMapping": {
      "username": "urn:oid:0.9.2342.19200300.100.1.1",
      "name": "urn:oid:2.16.840.1.113730.3.1.241"
    }
  },
  "your_idp_name2": {
    "entryPoint": "entrypoint2",
    "issuer": "urn:test",
    "identifierFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic",
    "enable":"false",
    "cert":"the cert",
    "acceptedClockSkewMs": 20000,
    "reverseMapping": {
      "email" : "email",
      "username": "urn:oid:0.9.2342.19200300.100.1.1",
      "members": "urn:1.3.6.1.4.1.48710.1.3.121",
      "provider" :"issuer"
    }
  }
}

and passport_saml script with:

...
oxConfigurationProperty: {"value1":"generic_remote_attributes_list","value2":"username, email, name, provider, members"}
oxConfigurationProperty: {"value1":"generic_local_attributes_list", "value2":"uid, mail, displayName, provider, memberOf"}
...

The providers generated will look like:

...
  {
	"id": "your_idp_name1",
	"displayName": "your_idp_name1",
	"type": "saml",
	"enabled": true,
	"passportStrategyId": "passport-saml",        
	"mapping": "your_idp_name1",
	"options": {
	    "entryPoint": "https://idp1.example.com/idp/profile/SAML2/POST/SSO",
	    "issuer": "urn:test:example",
	    "identifierFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
	    "cert": "your_idp_public_certicate_in_single_line"
	}
  },
  {
	"id": "your_idp_name2",
	"displayName": "your_idp_name2",
	"type": "saml",
	"enabled": false,
	"passportStrategyId": "passport-saml",        
	"mapping": "your_idp_name2",
	"options": {
	    "entryPoint": "entrypoint2",
	    "issuer": "urn:test",
	    "identifierFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic",
	    "cert": "the cert",
	    "acceptedClockSkewMs": "20000"
	}
  }

And the following files must have been created in directory ~/temp/mappings:

your_idp_name1.json:

module.exports = profile => {
	return {
	      uid: profile["urn:oid:0.9.2342.19200300.100.1.1"],
	      displayName: profile["urn:oid:2.16.840.1.113730.3.1.241"]
	}
}

your_idp_name2.json:

module.exports = profile => {
	return {
	      uid: profile["urn:oid:0.9.2342.19200300.100.1.1"],
	      mail: profile["email"],
	      memberOf: profile["urn:1.3.6.1.4.1.48710.1.3.121"]
	}
}

Important:

At the end, there will be only one gluuPassportConfiguration attribute in LDAP condensing the 3 sections (conf, idpInitiated, and providers). This means that existing values (ie. related to oauth providers) will be removed.

Cleaning

After generating contents for gluuPassportConfiguration attribute, the following should be done:

  • Add a .bak suffix to files passport-saml-config.json, passport-inbound-idp-initiated.json. Example: passport-saml-config.json.bak

  • For passport_social and passport_saml scripts, remove the properties generic_remote_attributes_list and generic_local_attributes_list

  • Update both scripts with the latest content (oxScript attr) and increase oxRevision attribute by one

  • Backup the current node app /opt/gluu/node/passport and replace with latest app from https://ox.gluu.org/npm/passport/

  • Install the app (npm install ...)

  • Start passport