In This post we will learn how One can implement OAuth Functionality in our visualforce login form page .
you see alot of login form over web provide Log In With Google functionality to there users so if you also want to implement OAuth in your form you need to follow the below steps .
So Before going to the code lets understand what is O AUTH :
O AUTH (Open Authorization) :
O AUTH allows an application to gain access to users data with another application without knowing the user password for the second application .
Here user who is using the application A but A wants some data which application B has For the user.
Instead of user sharing his user and password of application B with A . Through O AUTH application A will redirect user to application B where he will login and from that point of time application B will share a security token to application A . Using which these two communicate and application A will get all data which it requires from application B.
This process of logging and getting authorized this entire workflow is covered in the auth standard .
Mostly O AUTH is used in application login form to authenticate user .
Below are the steps you need to follow :
- You need to register yourself to developers.google.com. and then create an app. here we need to create an app because we need ID and App Secret Key .These are available only when you create an app. you need to also set redirection url variable Redirection url is the url to which you want to redirect user after authentication. (NOTE : Your redirection url should be the same visualforce login form page because we are performing all calculation in that page later we redirect our user to right page after some check. we redirect our user to success page from our controller not from google redirection url )
- save secret keys , google credentials to custom setting(donot worry you will get secret keys and credentials after you develop app) so that we can use it during integration.
- Create A visualforce page login form and implement OAuth functionality.
GoogleAuthLoginForm : Here is our visusalforce page login form code.
In this page Action we are calling googleSignIn Method For google O Auth
<apex:page controller="loginController" showHeader="false" sidebar="false" cache="false" standardStylesheets="false" action="{!googleSignIn}"> <style> body {font-family: Arial, Helvetica, sans-serif;} form {border: 3px solid #f1f1f1;} input[type=text], input[type=password] { width: 100%; padding: 12px 20px; margin: 8px 0; display: inline-block; border: 1px solid #ccc; box-sizing: border-box; } button { background-color: #4CAF50; color: white; padding: 14px 20px; margin: 8px 0; border: none; cursor: pointer; width: 100%; } button:hover { opacity: 0.8; } .cancelbtn { width: auto; padding: 10px 18px; background-color: #f44336; } .imgcontainer { text-align: center; margin: 24px 0 12px 0; } img.avatar { width: 40%; border-radius: 50%; } .container { padding: 50px;; width: 50%; border: 2px solid lightslategrey; margin: 23%; margin-top: 10%; } span.psw { float: right; padding-top: 16px; } .button { background-color: #4CAF50; /* Green */ border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; } /* Change styles for span and cancel button on extra small screens */ @media screen and (max-width: 300px) { span.psw { display: block; float: none; } .cancelbtn { width: 100%; } } .forgotPassword{ display : block; } .hide{ display: none; } .forgotPassword{ color:red; padding-top: 5%; } .button2 {background-color: #008CBA;} </style> <script> function googleOauth() { getAccessToken(); } window.onload = function() { console.log(gup('code', window.location)); }; function gup( name, url ) { if (!url) url = location.href; name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); var regexS = "[\\?&]"+name+"=([^&#]*)"; var regex = new RegExp( regexS ); var results = regex.exec( url ); return results == null ? null : results[1]; } function forgotPassword(){ var element = document.getElementById("forgotPasswordContainer"); element.classList.remove("hide"); var element = document.getElementById("forgotPasswordContainer"); element.classList.add("forgotPassword"); } function cancelForgotPassword(){ var element = document.getElementById("forgotPasswordContainer"); element.classList.remove("forgotPassword"); var element = document.getElementById("forgotPasswordContainer"); element.classList.add("hide"); } function signIn(){ } </script> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <body> <apex:form > <apex:actionFunction name="getAccessToken" action="{!getAccessToken}"/> </apex:form> <div class="container"> <div class="loginContainer"> <div style="color:red;">{!errMsg}</div> <div class="fieldsButton" id="loginContainer"> <div class="label">Username</div> <div class="field"> <input type="text" id="username"/> </div> <div class="label">Password</div> <div class="field"> <input type="password" id="password"/> </div> <div class="centered"> <div class="button" onclick="signIn();"><div class="buttonText">SIGN IN</div></div> <div class="signInAluButton button button2" onclick="googleOauth();"> <i class="fa fa-sign-in fa-2x buttonIcon" aria-hidden="true"/> <div class="buttonText">Sign In with google</div> </div> </div> </div> <div class="forgotPassword" onclick="forgotPassword();">Forgot Password?</div> <div class="fieldsButton hide" id="forgotPasswordContainer"> <div class="label">Enter your username</div> <div class="field"> <input type="text" id="retrievePassword"/> </div> <div class="centered"> <div class="button" onclick="receivePassword();"> <div class="buttonText">Receive Password</div> </div> <div class="button" onclick="cancelForgotPassword();" style="margin: 5px;"> <div class="buttonText">Cancel</div> </div> </div> </div> </div> </div> </body> </apex:page>
Apex Class Controller Method Code Description :
public class loginController
{
public string errMsg{get;set;}
// main method used for api calling and redirection after matching email with contact email
public PageReference googleSignIn()
{
try
{
String code = ApexPages.currentPage().getParameters().get(‘code’);
system.debug(‘value of code is @@@@@’+code);
if(String.isNotBlank(code))
{
// getting all the values from custom labels
String clientId = Label.GoogleClientId;
String clientSecret = Label.GoogleClientSecret;
String redirectURI = Label.GoogleRedirectURI;
// request for access token
HttpRequest req = new HttpRequest();
String body=’code=’+code+’&client_id=’+clientId+’&client_secret=’+clientSecret+’&redirect_uri=’+redirectURI+’&grant_type=authorization_code’;
req.setEndpoint(‘https://accounts.google.com/o/oauth2/token’);
req.setMethod(‘POST’);
req.setHeader(‘Content-Type’,’application/x-www-form-urlencoded’);
req.setBody(body);
Http http = new Http();
HttpResponse res = http.send(req);
String response = res.getBody();
system.debug(‘value of response is @@@@@’+response);
if(res.getStatusCode() == 200)
{
Map<String,Object> accessTokenMap = (Map<String,Object>)JSON.deserializeUntyped(response);
system.debug(‘value of accessTokenMap is @@@@@’+accessTokenMap);
String accTok = String.valueOf(accessTokenMap.get(‘access_token’));
system.debug(‘value of accTok’+accTok);
// After getting access token we send second request to google people api to get user email by sending access token in request
if(String.isNotBlank(accTok))
{
HttpRequest req1 = new HttpRequest();
req1.setEndpoint(‘https://www.googleapis.com/plus/v1/people/me’);
req1.setMethod(‘GET’);
req1.setHeader(‘Authorization’,’Bearer ‘+accTok);
Http http1 = new Http();
HttpResponse res1 = http1.send(req1);
String emailResponse = res1.getBody();
if(String.isNotBlank(emailResponse))
{
Map<String,Object> emailMap = (Map<string,object>)JSON.deserializeUntyped(emailResponse);</string,object>
List<Object> emailValueList = (List<Object>)emailMap.get(’emails’);
String emailJSON = JSON.serialize(emailValueList);
emailJSON = emailJSON.removeStart(‘[‘).removeEnd(‘]’);
// deserialize into apex wrapper
googleEmailWrapper gewList = (googleEmailWrapper)JSON.deserialize(emailJSON, googleEmailWrapper.class);
if(gewList != null)
{
String email = gewList.value;
if(String.isNotBlank(email))
{
// getting all the contacts
List<Contact> stuEmails = [SELECT Id,Email__c FROM Contact LIMIT 50000];
if(stuEmails != null && stuEmails.size() > 0)
{
boolean isMatch = false;
// checking either there is any contact match with response email id
for(Contact ss: stuEmails)
{
// If email id matched then store data in cookies and redirect user to success page
if(ss.Email__c == email)
{
Cookie coo = new Cookie(‘con’,ss.Id,null,-1,false);
PageReference ref = new PageReference(‘apex/success’);
ref.setCookies(new Cookie[]{coo});
ref.setRedirect(true);
isMatch = true;
return ref;
}
}
if(!isMatch)
{
errMsg = ‘ERROR: Email ID not found in our system, please use your registered email to sign in.’;
return null;
}
}
}
}
}
}
}
else
{
errMsg = ‘ERROR: Session expired, please login again.’;
return null;
}
return null;
}
else
{
errMsg = ”;
return null;
}
}
catch(Exception e)
{
errMsg = ‘ERROR: ‘+e.getMessage()+’ – ‘+e.getLineNumber();
return null;
}
}
// this method is only used for simple logged in
@RemoteAction
public static String login(String username, String password)
{
try
{
List<Contact> stuList = [SELECT Id,Username__c,Password__c
FROM Contact
WHERE Username__c != null AND Username__c != ”
LIMIT 50000];
Map<String,Contact> stuMap = new Map<String,Contact>();
if(stulist != null && stulist.size() > 0)
{
For(Contact stu: stulist)
{
If(String.isNotBlank(stu.Username__c))
{
stuMap.put(stu.Username__c,stu);
}
}
if(stuMap.containsKey(username))
{
Contact stu = stuMap.get(username);
if(stu != null && String.isNotBlank(stu.Password__c))
{
if(stu.Password__c != password)
{
return ‘Password does not match.’;
}
else
{
return ‘Success-‘+stu.Id;
}
}
else
{
return ‘Your account has been deactivated or deleted. Please contact your system administrator.’;
}
}
else
{
return ‘Username does not exist.’;
}
}
else
{
return ‘No students found in the system. Please contact your system administrator.’;
}
}
catch(Exception e)
{
return ‘Error while signing in – ‘+e.getMessage()+’ – ‘+e.getLineNumber();
}
}
// forget password code
@RemoteAction
public static String receivePassword(String username)
{
try
{
List<Contact> stuList = [SELECT Id,Username__c,Password__c,Email__c,LastName
FROM Contact
WHERE Username__c != null AND Username__c != ”
LIMIT 50000];
Map<String,Contact> stuMap = new Map<String,Contact>();
if(stulist != null && stulist.size() > 0)
{
For(Contact stu: stulist)
{
If(String.isNotBlank(stu.Username__c))
{
stuMap.put(stu.Username__c,stu);
}
}
if(stuMap.containsKey(username))
{
Contact stu = stuMap.get(username);
if(stu != null && String.isNotBlank(stu.Password__c) && String.isNotBlank(stu.Email__c))
{
string[] toAddresses = new string[]{stu.Email__c};
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(toAddresses);
mail.setSubject(‘Password Recovery’);
mail.setHTMLBody(‘Hi ‘+stu.LastName+’,<br/><br/><b>Username</b> = ‘+stu.Username__c+'<br/><b>Password</b> = ‘+stu.Password__c+'<br/><br/>Thanks<br/>ALU Student Portal’);
Messaging.sendEmail(new Messaging.SingleEmailMessage[]{mail});
ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.CONFIRM,’Sent Successfully.’);
ApexPages.addMessage(myMsg);
return ‘Success’;
}
else
{
return ‘Your account has been deactivated or deleted. Please contact your system administrator.’;
}
}
else
{
return ‘Username does not exist.’;
}
}
else
{
return ‘No students found in the system. Please contact your system administrator.’;
}
}
catch(Exception e)
{
return ‘Error while signing in – ‘+e.getMessage()+’ – ‘+e.getLineNumber();
}
}
// code to get access token this method is called when user click on logged in with gmail button
public pageReference getAccessToken()
{
String googleURL = ‘https://accounts.google.com/o/oauth2/auth?scope=’+EncodingUtil.urlEncode(‘https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.profile.emails.read’,’UTF-8′)+’&state=’+EncodingUtil.urlEncode(‘/profile’,’UTF-8′)+’&redirect_uri=’+EncodingUtil.urlEncode(Label.GoogleRedirectURI,’UTF-8′)+’&response_type=code&client_id=’+’153604074017-oppjg691c9j2ak9ri3l1a5bgvr8t61d0.apps.googleusercontent.com’+’&approval_prompt=’+’force’;
PageReference ref = new PageReference(googleURL);
ref.setRedirect(true);
return ref;
}
// wrapper class to store response data
public class googleEmailWrapper
{
public string type;
public string value;
}
}
OUTPUT :
Hits: 1949