You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
GNIP 94: Generic and pluggable OIDC SocialAccount Provider for GeoNode
Overview
Currently GeoNode provides by default 2 quite old and outdated SOCIALACCOUNT providers, LinkedIn and Facebook, which are based on OAuth2 and make use of very old plugins.
Today the reference protocol is OIDC, and GeoNode users increasingly need to be able to link their accounts to providers that support and implement this technology. Two of the most commonly used providers are Google and Microsoft Azure, for example.
The purpose of this proposal is to revise the SocialAccount and SocialProvider classes in GeoNode in order to not only make them capable of handling the more modern OIDC protocol but also to take advantage of some of its features, such as extracting user information from the id_token after validating its origin, among others.
Furthermore, a significant benefit of this technology is that the protocol is now a widely respected standard among all providers. This allows us to create dynamic, modular, and scalable structures that enable GeoNode to handle almost all use cases through a few configuration parameters.
Notice that the class is fully customizable, from the name, the account class to the common fields that we would like to extract from the JSON user-info response.
All those parameters can be driver by the GeoNode settings
A fully pluggable Provider configuration
From the settings point of view, configuring the provider will simply require to fill the common customizable properties of the OIDC authority.
As an instance, the following ones are two sample configurations for Google and Microsofr Azure
By updating the SOCIALACCOUNT_PROVIDERS dictionary you can easily switch from a provider to another.
Notice how their configuration is mostly the same. The only values the user should provide are the correct OIDC endpoints specific to the authority we would like to use.
The default AccountAdapter
Within the GeoNode classes will be available also a generic account provider which is defined like this
The GenericOpenIDConnectAdapter extends few common login methods which will allow us to seemlessly extract the user information both from the UserInfoURI and the IDToken
PROVIDER_ID=getattr(settings, "SOCIALACCOUNT_OIDC_PROVIDER", "geonode_openid_connect")
ACCESS_TOKEN_URL=getattr(settings, "SOCIALACCOUNT_PROVIDERS", {}).get(PROVIDER_ID, {}).get("ACCESS_TOKEN_URL", "")
AUTHORIZE_URL=getattr(settings, "SOCIALACCOUNT_PROVIDERS", {}).get(PROVIDER_ID, {}).get("AUTHORIZE_URL", "")
PROFILE_URL=getattr(settings, "SOCIALACCOUNT_PROVIDERS", {}).get(PROVIDER_ID, {}).get("PROFILE_URL", "")
ID_TOKEN_ISSUER=getattr(settings, "SOCIALACCOUNT_PROVIDERS", {}).get(PROVIDER_ID, {}).get("ID_TOKEN_ISSUER", "")
classGenericOpenIDConnectAdapter(OAuth2Adapter, SocialAccountAdapter):
provider_id=PROVIDER_IDaccess_token_url=ACCESS_TOKEN_URLauthorize_url=AUTHORIZE_URLprofile_url=PROFILE_URLid_token_issuer=ID_TOKEN_ISSUERdefcomplete_login(self, request, app, token, response, **kwargs):
extra_data= {}
ifself.profile_url:
headers= {"Authorization": "Bearer {0}".format(token.token)}
resp=requests.get(self.profile_url, headers=headers)
profile_data=resp.json()
extra_data.update(profile_data)
elif"id_token"inresponse:
try:
extra_data=jwt.decode(
response["id_token"],
# Since the token was received by direct communication# protected by TLS between this library and Google, we# are allowed to skip checking the token signature# according to the OpenID Connect Core 1.0# specification.# https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidationoptions={
"verify_signature": False,
"verify_iss": True,
"verify_aud": True,
"verify_exp": True,
},
issuer=self.id_token_issuer,
audience=app.client_id,
)
exceptjwt.PyJWTErrorase:
raiseOAuth2Error("Invalid id_token") fromelogin=self.get_provider().sociallogin_from_response(request, extra_data)
returnlogindefsave_user(self, request, sociallogin, form=None):
user=super(SocialAccountAdapter, self).save_user(request, sociallogin, form=form)
extractor=get_data_extractor(sociallogin.account.provider)
try:
groups=extractor.extract_groups(sociallogin.account.extra_data) orextractor.extract_roles(
sociallogin.account.extra_data
)
# check here if user is member already of other groups and remove it form the ones that are not declared here...forgroupprofileinuser.group_list_all():
groupprofile.leave(user)
forgroup_nameingroups:
groupprofile=GroupProfile.objects.filter(slug=group_name).first()
ifgroupprofile:
groupprofile.join(user)
except (AttributeError, NotImplementedError):
pass# extractor doesn't define a method for extracting fieldreturnuser
The complete_login method will check whether we want to extract the user extra-info Json data from the id_token or from the user-info endpoint.
The save_user method will extract the commond fields from the Json data by making a mapping between the Json properties and the GeoNode UserProfile model.
Moreover it will check if the returned data declares some Groups or Roles the user belongs to. In that case it will check if the corresponding GroupProfile exists already on the GeoNode database and automatically assign the user to it.
Backwards Compatibility
No backwards compatibility.
Future evolution
Add more sample configurations for the most popular OIDC providers.
giohappy
changed the title
GNIP-93: Generic and pluggable OIDC SocialAccount Provider for GeoNode
GNIP-94: Generic and pluggable OIDC SocialAccount Provider for GeoNode
Jul 4, 2023
giohappy
changed the title
GNIP-94: Generic and pluggable OIDC SocialAccount Provider for GeoNode
GNIP 94: Generic and pluggable OIDC SocialAccount Provider for GeoNode
Jul 4, 2023
GNIP 94: Generic and pluggable OIDC SocialAccount Provider for GeoNode
Overview
Currently GeoNode provides by default 2 quite old and outdated
SOCIALACCOUNT
providers,LinkedIn
andFacebook
, which are based onOAuth2
and make use of very old plugins.Today the reference protocol is
OIDC
, and GeoNode users increasingly need to be able to link their accounts to providers that support and implement this technology. Two of the most commonly used providers are Google and Microsoft Azure, for example.The purpose of this proposal is to revise the
SocialAccount
andSocialProvider
classes in GeoNode in order to not only make them capable of handling the more modern OIDC protocol but also to take advantage of some of its features, such as extracting user information from theid_token
after validating its origin, among others.Furthermore, a significant benefit of this technology is that the protocol is now a widely respected standard among all providers. This allows us to create dynamic, modular, and scalable structures that enable GeoNode to handle almost all use cases through a few configuration parameters.
Proposed By
@afabiani
Assigned to Release
This proposal is for GeoNode 4.1.2+.
State
Proposal
The
geonode_openid_connect
social account providerThis will be the generic class which will allow us handling the OIDC social login
Notice that the class is fully customizable, from the
name
, theaccount class
to thecommon fields
that we would like to extract from theJSON
user-info response.All those parameters can be driver by the GeoNode
settings
A fully pluggable Provider configuration
From the
settings
point of view, configuring the provider will simply require to fill the common customizable properties of the OIDC authority.As an instance, the following ones are two sample configurations for
Google
andMicrosofr Azure
By updating the
SOCIALACCOUNT_PROVIDERS
dictionary you can easily switch from a provider to another.Notice how their configuration is mostly the same. The only values the user should provide are the correct OIDC endpoints specific to the authority we would like to use.
The default
AccountAdapter
Within the GeoNode classes will be available also a generic account provider which is defined like this
The
GenericOpenIDConnectAdapter
extends few commonlogin
methods which will allow us to seemlessly extract the user information both from theUserInfoURI
and theIDToken
The
complete_login
method will check whether we want to extract the userextra-info
Json data from theid_token
or from theuser-info
endpoint.The
save_user
method will extract the commond fields from the Json data by making a mapping between the Json properties and the GeoNodeUserProfile
model.Moreover it will check if the returned data declares some
Groups
orRoles
the user belongs to. In that case it will check if the correspondingGroupProfile
exists already on the GeoNode database and automatically assign the user to it.Backwards Compatibility
No backwards compatibility.
Future evolution
Add more sample configurations for the most popular OIDC providers.
Feedback
Voting
Project Steering Committee:
Links
Remove unused links below.
The text was updated successfully, but these errors were encountered: