├── .gitattributes
├── .gitignore
└── src
├── authproviders
└── Twitter.authprovider
├── classes
├── TwitterClientCredentialsAuth.cls
└── TwitterClientCredentialsAuth.cls-meta.xml
├── customMetadata
└── TwitterAuth.Twitter.md
├── layouts
└── TwitterAuth__mdt-Twitter Auth Layout.layout
├── namedCredentials
├── TwitterAPI.namedCredential
└── TwitterTokenService.namedCredential
├── objects
└── TwitterAuth__mdt.object
└── package.xml
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # Windows shortcuts
18 | *.lnk
19 |
20 | # =========================
21 | # Operating System Files
22 | # =========================
23 |
24 | # OSX
25 | # =========================
26 |
27 | .DS_Store
28 | .AppleDouble
29 | .LSOverride
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear in the root of a volume
35 | .DocumentRevisions-V100
36 | .fseventsd
37 | .Spotlight-V100
38 | .TemporaryItems
39 | .Trashes
40 | .VolumeIcon.icns
41 |
42 | # Directories potentially created on remote AFP share
43 | .AppleDB
44 | .AppleDesktop
45 | Network Trash Folder
46 | Temporary Items
47 | .apdisk
48 |
--------------------------------------------------------------------------------
/src/authproviders/Twitter.authprovider:
--------------------------------------------------------------------------------
1 |
2 |
3 | TwitterAuth__mdt.Twitter
4 | user@example.com
5 | Twitter
6 | false
7 | TwitterClientCredentialsAuth
8 | Custom
9 | false
10 | false
11 |
12 |
--------------------------------------------------------------------------------
/src/classes/TwitterClientCredentialsAuth.cls:
--------------------------------------------------------------------------------
1 | public class TwitterClientCredentialsAuth extends Auth.AuthProviderPluginClass {
2 |
3 | // Name for this auth provider.
4 | private String authProvider = 'Twitter';
5 |
6 | // Api name for the custom metadata type created for this auth provider.
7 | private String customMetadataTypeApiName = 'TwitterAuth__mdt';
8 |
9 | // Name for the generic username displayed in the named credential configuration.
10 | private String userName = 'Anonymous User';
11 |
12 | // Type of token.
13 | private String tokenType = 'secret';
14 |
15 | // Structure of a token response from Twitter
16 | public class TwitterResponse {
17 | public String token_type;
18 | public String access_token;
19 | }
20 |
21 | //name of custom metadata type to embed configuration fields in auth provider
22 | public String getCustomMetadataType() {
23 | return customMetadataTypeApiName;
24 | }
25 |
26 | //directly redirect the user back to the callback URL, as we already have the client key and secret
27 | //to be used for authenticating directly
28 | public PageReference initiate(Map authProviderConfiguration, String stateToPropagate) {
29 | return new PageReference(authProviderConfiguration.get('Callback__c') +'?state=' +stateToPropagate);
30 | }
31 |
32 | //handle instantaneous callback and then use named credetial (username and password / client key and secret) to retrieve access token
33 | public Auth.AuthProviderTokenResponse handleCallback(Map authProviderConfiguration, Auth.AuthProviderCallbackState state ) {
34 | return new Auth.AuthProviderTokenResponse(authProvider, retrieveToken(authProviderConfiguration.get('NamedCredential__c')), tokenType, state.queryParameters.get('state'));
35 | }
36 |
37 | //if access token expired, reuse named credetial 4to retrieve access token
38 | public override Auth.OAuthRefreshResult refresh(Map authProviderConfiguration, String refreshToken) {
39 | return new Auth.OAuthRefreshResult(retrieveToken(authProviderConfiguration.get('NamedCredential__c')), tokenType);
40 | }
41 |
42 | //return fake username, as client_credential auth is not tied to a specific user
43 | public Auth.UserData getUserInfo(Map authProviderConfiguration, Auth.AuthProviderTokenResponse response) {
44 | return new Auth.UserData(null, null, null, null, null, null, userName, null, authProvider, null, new Map());
45 | }
46 |
47 | //make HTTP call to token endpoint using client credentials to retrieve access token
48 | private String retrieveToken(String namedCredential) {
49 |
50 | HttpRequest req = new HttpRequest();
51 |
52 | req.setEndpoint('callout:'+namedCredential);
53 | req.setHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8');
54 | req.setMethod('POST');
55 | req.setBody('grant_type=client_credentials');
56 |
57 | HTTPResponse res = new Http().send(req);
58 |
59 | return deserialiseToken(res);
60 | }
61 |
62 | //deserialise response and return token
63 | private String deserialiseToken(HTTPResponse res) {
64 |
65 | String responseBody = res.getBody();
66 |
67 | TwitterResponse parsedResponse = (TwitterResponse) System.JSON.deserialize(responseBody, TwitterResponse.class);
68 |
69 | return parsedResponse.access_token;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/classes/TwitterClientCredentialsAuth.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/src/customMetadata/TwitterAuth.Twitter.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 | Callback__c
7 | https://test.salesforce.com/services/authcallback/OrgId/AuthProviderName
8 |
9 |
10 | NamedCredential__c
11 | TwitterTokenService
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/layouts/TwitterAuth__mdt-Twitter Auth Layout.layout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | false
6 | true
7 |
8 |
9 |
10 | Required
11 | MasterLabel
12 |
13 |
14 | Required
15 | DeveloperName
16 |
17 |
18 | Edit
19 | Callback__c
20 |
21 |
22 | Edit
23 | NamedCredential__c
24 |
25 |
26 |
27 |
28 | Edit
29 | IsProtected
30 |
31 |
32 | Required
33 | NamespacePrefix
34 |
35 |
36 |
37 |
38 |
39 | false
40 | false
41 | true
42 |
43 |
44 |
45 | Readonly
46 | CreatedById
47 |
48 |
49 |
50 |
51 | Readonly
52 | LastModifiedById
53 |
54 |
55 |
56 |
57 |
58 | false
59 | false
60 | false
61 |
62 |
63 |
64 | false
65 | false
66 | false
67 | false
68 | false
69 |
70 |
--------------------------------------------------------------------------------
/src/namedCredentials/TwitterAPI.namedCredential:
--------------------------------------------------------------------------------
1 |
2 |
3 | Twitter
4 | https://api.twitter.com
5 |
6 | NamedUser
7 | Oauth
8 |
9 |
--------------------------------------------------------------------------------
/src/namedCredentials/TwitterTokenService.namedCredential:
--------------------------------------------------------------------------------
1 |
2 |
3 | https://api.twitter.com/oauth2/token
4 |
5 | NamedUser
6 | Password
7 | ClientKey
8 |
9 |
--------------------------------------------------------------------------------
/src/objects/TwitterAuth__mdt.object:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Callback__c
5 | false
6 | DeveloperControlled
7 |
8 | 255
9 | false
10 | Text
11 | false
12 |
13 |
14 | NamedCredential__c
15 | false
16 | DeveloperControlled
17 |
18 | 255
19 | false
20 | Text
21 | false
22 |
23 |
24 | Twitter Authentication Configurations
25 | Public
26 |
27 |
--------------------------------------------------------------------------------
/src/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TwitterClientCredentialsAuth
5 | ApexClass
6 |
7 |
8 | Twitter
9 | AuthProvider
10 |
11 |
12 | TwitterAuth__mdt.Callback__c
13 | TwitterAuth__mdt.NamedCredential__c
14 | CustomField
15 |
16 |
17 | TwitterAuth.Twitter
18 | CustomMetadata
19 |
20 |
21 | TwitterAuth__mdt
22 | CustomObject
23 |
24 |
25 | TwitterAuth__mdt-Twitter Auth Layout
26 | Layout
27 |
28 |
29 | TwitterAPI
30 | TwitterTokenService
31 | NamedCredential
32 |
33 | 40.0
34 |
35 |
--------------------------------------------------------------------------------