# Link with Patreon

**URL:** <https://forum.keycloak.org/t/link-with-patreon/24639>\
**Category:** Getting advice\
**Created:** [February 19, 2024, 10:59pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639 "2024-02-19T22:59:33Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 19, 2024, 10:59pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/1 "2024-02-19T22:59:33Z")

</div>

**Context**  
I am adding user accounts to my website with the help of keycloak. Registration and Login works. Now I try to provide a button to link a patreon account, so users can get more features if they are supporting me on [patreon.com](http://patreon.com). I wanted to use the keycloak social link feature and thought I don’t need to save any additional data in an own database (beside the stuff keycloak is persisting about my users).

The problem is, that the patreon API is not using OIDC (but OAuth and an /identity endpoint) and keycloak on the other side always sends the ‘openid’ scope, leading to errors on the patreon side.

I already did a lot of research but I am unsuccessful in a way that makes me think I miss something obvious.  
I thought both patreon and keycloak are quite common so I would think there could be a provider already included in keycloak. But I don’t even find any community stuff by searching the web.

**Specific questions**

- **Does anyone know of an implementation connecting keycloak\<-\>patreon?**
- **When I do the connection myself - Can I still save the patreon data to keycloak?**  
I can read the Patreon API myself on the backend of my app. I could save the patreon user data and refresh tokens in an own database but it would be great if I could somehow add that data directly to the user account on keycloak instead. Is this possible?
- **Additional questions that seem like I should change the whole approach**  
When I do the API communication with patreon myself, I need to do it on the server as it needs a clientId and secret but at the moment I only do the communication with my keycloak on the frontend (public client with pkce).  
As I can’t add the Bearer Token as a Header to the redirect coming from patreon, the token with data about the user logged in to my site needs to be transmitted somehow else (I need both the patreon data and the logged in user to be able to connect them). For example, after the login is done on the frontend I could set a cookie. It wouldn’t be httpOnly but as frontend JS is doing everything at the moment XSS attacks are problematic anyway. I guess I should switch to a server side auth and a session to get rid of the XSS problem and be able to connect patreon and my user account more easily. This all seem to be more complex than necessary but I don’t see an easy alternative despite the use case that seems pretty common to me.  
Writing a patreon identity provider for keycloak in java seems like the other right thing to do, but then it would probably have been done already?!

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [February 20, 2024, 12:40pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/2 "2024-02-20T12:40:24Z")

</div>

If you want to implement your own identity provider, it looks like there is enough in the Patreon [OAuth2 implementation](https://docs.patreon.com/#apiv2-oauth) + [User identity resource](https://docs.patreon.com/#get-api-oauth2-v2-identity) to create one. Look at the GitHub identity provider code for an example [keycloak/services/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java at main · keycloak/keycloak · GitHub](https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java)

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 26, 2024, 6:48pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/3 "2024-02-26T18:48:32Z")

</div>

Thanks @xgp for your answer and the links!  
**I am now implementing an identity provider** and am already getting the json data from patreon. I am not using the link to create new users but only to connect existing users with patreon accounts.

**It would be great to get some tipps on how to save/map the patreon data!**

- Data like `name`, `email` etc is not important for me and I am not retrieving them at the moment.
- What is important is how much the user is paying me on patreon (or maybe to which tier/membership he subscribed).

Here is an example json I get from patreon

```auto
{
	"data": {
		"attributes": {},
		"id": "123456789",
		"relationships": {
			"memberships": {
				"data": [
					{
						"id": "e4d8ae89-...",
						"type": "member"
					}
				]
			}
		},
		"type": "user"
	},
	"included": [
		{
			"attributes": {
				"campaign_lifetime_support_cents": 100,
				"patron_status": "active_patron"
			},
			"id": "e4d8ae89-...",
			"relationships": {
				"currently_entitled_tiers": {
					"data": [
						{
							"id": "1231231",
							"type": "tier"
						}
					]
				}
			},
			"type": "member"
		},
		{
			"attributes": {
				"amount_cents": 100,
				"title": "Test Supporter",
				"url": "/checkout/myurl?rid=1231231"
			},
			"id": "1231231",
			"type": "tier"
		}
	],
	"links": {
		"self": "https://www.patreon.com/api/oauth2/v2/user/123456789"
	}
}

```

I guess it makes sense to not only save that data to keycloak but **map that to a role**. This way I could add multiple social providers in the future and don’t need to know them in my apps. Features would be available because of roles.  
Nevertheless it would be great to see the **patreon data in the JWT** as well to display something like “because you pay me 3eur per month on patreon you can xyz” on the website and add a link to his patreon account or similar

Does this sound plausible or am I thinking in a wrong direction?  
Any examples for that?

Thanks a lot!

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [February 26, 2024, 7:53pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/4 "2024-02-26T19:53:16Z")

</div>

I think that’s the right direction. I would suggest looking at the other social providers for examples of what other implementations do with the data they get back from the provider. Then start with the simplest possible set.

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 27, 2024, 1:11pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/5 "2024-02-27T13:11:40Z")

</div>

Thanks a lot again @xgp!!

Any idea why I can only select one of the following 3 mappers for my custom identity provider in the keycloak admin gui?

- Hardcoded Attribute
- Hardcoded Role
- Hardcoded User Session Attribute

I need a mapper that sets a role depending on the values in the json retrievd from the linked IDP.  
Which Mapper would fit to set a role if  
`"patron_status" == "active_patron"`  
AND  
`"amount_cents" > 300`

in the example json above and how can I make that mapper be selectable?

* * *

I call `AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, patreonJson, getConfig().getAlias());` in my Provider. I guess that’s enough to let the Mapper have access to the data!?

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 27, 2024, 1:20pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/6 "2024-02-27T13:20:44Z")

</div>

I just tested “Add Mapper” with a github and facebook IDP and both have those 3 “Hardcoded…” Mappers and two others (Attribute Importer, Username Template Importer).

I thought a role is the thing to add but I guess an attribute works as well, as long as it comes up in the Keycloak JWT. So I guess the “Attribute Importer” would be one way to make that work

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [February 27, 2024, 6:18pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/7 "2024-02-27T18:18:25Z")

</div>

I’d also take a look at writing your own `IdentityProviderMapper`. Take a look at [AbstractIdentityProviderMapper (Keycloak Docs Distribution 23.0.7 API)](https://www.keycloak.org/docs-api/23.0.7/javadocs/org/keycloak/broker/provider/AbstractIdentityProviderMapper.html) which has a lot of base classes for mapping into Group/Role/Attribute/etc. There will be example implementations for how to use them in the code for the Keycloak social providers [keycloak/services/src/main/java/org/keycloak/social at main · keycloak/keycloak · GitHub](https://github.com/keycloak/keycloak/tree/main/services/src/main/java/org/keycloak/social)

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 28, 2024, 1:25pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/8 "2024-02-28T13:25:43Z")

</div>

As a first test I tried to add a mapper like the one of the github provider. I added a class PatreonAttributeMapper.java with the following content

```auto
public class PatreonAttributeMapper extends AbstractJsonUserAttributeMapper {
    
    public static final String MAPPER_ID = "patreon-user-attribute-mapper";
	private static final String[] cp = new String[] { PatreonIdentityProviderFactory.PROVIDER_ID };

	@Override
	public String[] getCompatibleProviders() {
		return cp;
	}

	@Override
    public String getId() {
        return MAPPER_ID;
    }
    
}

```

I still only get those same 3 Mappers in the admin GUI.  
Any idea what is missing to add more mappers (my mapper) in the dropdown?

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 28, 2024, 4:04pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/9 "2024-02-28T16:04:47Z")

</div>

I did another test

1. Added the `Hardcoded Role` Mapper to my provider in the admin gui and selected a test role.
2. Unlinked and linked my test user again

I thought now the user would have that test role but it does not. Any idea why?

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [February 28, 2024, 6:25pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/10 "2024-02-28T18:25:06Z")

</div>

It’s hard to tell without seeing all of your code, but have you registered the mapper in the `META-INF/services /org.keycloak.broker.provider.IdentityProviderMapper` file?

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 28, 2024, 10:50pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/11 "2024-02-28T22:50:32Z")

</div>

Thanks a lot!! With this change the mapper is now selectable in the drop down!

Is this documented somewhere? Maybe I have overlooked some docs that can help?

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [February 29, 2024, 1:22am UTC](https://forum.keycloak.org/t/link-with-patreon/24639/12 "2024-02-29T01:22:03Z")

</div>

My mapper is active but I am not successful with adding the role.  
I use `HardcodedRoleMapper` as an Example. It adds the role [in `importNewUser`](https://github.com/keycloak/keycloak/blob/326d63ce7462cbcd94f2efde2eb9070c1a724220/services/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java#L94C17-L94C30) and [in `updateBrokeredUser`](https://github.com/keycloak/keycloak/blob/326d63ce7462cbcd94f2efde2eb9070c1a724220/services/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java#L119)

I have added log messages in my mapper to

1. `preprocessFederatedIdentity`
2. `importNewUser`
3. `updateBrokeredUser`

only the first is called. But this method gets no UserModel. The `HardcodedRoleMapper` adds the role via `UserModel->grantRole`

I found the method `context.addMapperGrantedRole(nameOfRoleToAdd)` but I saw [in AbstractAttributeToRoleMapper](https://github.com/keycloak/keycloak/blob/326d63ce7462cbcd94f2efde2eb9070c1a724220/services/src/main/java/org/keycloak/broker/saml/mappers/AbstractAttributeToRoleMapper.java#L64) that this is also used in `updateBrokeredUser`.

- **Should `updateBrokeredUser` be called?**

Note: I don’t use the external IDP to import new users but do [client initiated account linking](https://www.keycloak.org/docs/21.1.2/server_development/index.html#client-initiated-account-linking).

I see in the code that it should be called in IdentityProviderMapperSyncModeDelegate-\>delegateUpdateBrokeredUser if the sync mode is FORCE. It is FORCE…I log that.

I am working backwards through the code from there, but maybe you have a better idea or know why updateBrokeredUser is not called.

Thanks a lot again for your help!

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [February 29, 2024, 6:20pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/13 "2024-02-29T18:20:16Z")

</div>

Yes, it’s in the Server Developer documentation. E.g. [Server Developer Guide](https://www.keycloak.org/docs/latest/server_development/index.html#_implementing_spi)

---

<div class="post-metadata">

**Author:** ![xgp](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/xgp/32/2589_2.png) [@xgp](https://forum.keycloak.org/u/xgp)\
**Post date:** [February 29, 2024, 6:21pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/14 "2024-02-29T18:21:27Z")

</div>

This is a good example of really needing to see the code in order to be able to help. I roughly follow your questions in this message, but it would be impossible to really help without seeing the code and being able to test.

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [March 4, 2024, 11:14pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/15 "2024-03-04T23:14:04Z")

</div>

I found a keycloak bug while stepping through the code and I also found the fix that was added 9 months ago.  
I don’t know why but my docker pulls an old keycloak image (21.0.2) when I use the “latest” tag in my Dockerfile. Now that I use “24.0” instead, it works and my role is added.

Thanks for your previous answers. i will publish my provider to github if I have other questions regarding my code.

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [March 5, 2024, 3:30pm UTC](https://forum.keycloak.org/t/link-with-patreon/24639/16 "2024-03-05T15:30:36Z")

</div>

**Current state**  
When the user links the patreon account to his keycloak account I get all necessary data and can add a role and additional attributes to his profile.

**Question**  
I thought the `Post login flow` can be used to let keycloak automatically update the ‘cached state’ of the brokered IDP. I thought keycloak saves the access and refresh token of the IDP and calls the provider/mapper when a linked user logs in.  
But after re-reading the docs I think this was a misinterpretation.  
**What’s the easiest way to reevaluate the linked data from time to time, e.g. when the user logs in?**

**Context**  
Users can pay a monthly fee at patreon and will have more features on my website. Of course I want to recognize when a user does not pay anymore and update the data saved in my keycloak (eg remove an added role).  
If I would have to retrieve those updates myself, I guess the whole Mapper makes no sense for me, right?

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [March 7, 2024, 9:22am UTC](https://forum.keycloak.org/t/link-with-patreon/24639/17 "2024-03-07T09:22:18Z")

</div>

To be more specific. I don’t want the user to redo the linking after each login.

So I guess I need a different flow for “first login flow” and “post login flow”, right?

Is there a fitting “post login flow” already selectable by configuration? So that keycloak gets the data of the brokered IDP after each login and uses my mapper again to update the cached user data?

Or do I need to provide an own EventListener to listen for login events, talk with the brokered idp and update the usermodel?  
Does it make sense in your opinion to add some kind of recurring job in my custom IdentityProvider that reads from the poatreon API lets say once a day and update cached user data?

---

<div class="post-metadata">

**Author:** ![andymel](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@andymel](https://forum.keycloak.org/u/andymel)\
**Post date:** [March 7, 2024, 10:05am UTC](https://forum.keycloak.org/t/link-with-patreon/24639/18 "2024-03-07T10:05:29Z")

</div>

By the way, my `Sync Mode` is still “Force”. Shouldn’t this setting alone be enough to let keycloak …

- call the external IDP again
- update the user data via my mappers `updateBrokeredUser`

… after each user login?!

My provider on github:

> **[GitHub - andymel123/keycloak-patreon-provider](https://github.com/andymel123/keycloak-patreon-provider)**
>
> Contribute to andymel123/keycloak-patreon-provider development by creating an account on GitHub.

**If the update is only done, when the user does the login via this IDP:**  
I guess it would make sense to add another sync mode then. At least patreon is a great use case for that, it should be updated on login also if the account is only linked. The naming could get interesting. ‘Force’ already sounds like it should do it.
