Adding a new BaaS method for executing a password reset email notification using Kinvey

Posted by on in Blogs
A couple of days ago, I covered how to add password reset functionality to your application for resetting the password inside your app.
A common question I got was how to leverage the cloud based password reset email functionality that many BaaS providers offer. Today, I thought I would cover how to add password reset functionality via an email notification to your BaaS enabled mobile application using RAD Studio XE6. This tutorial uses Kinvey, but I am going to do a blog post on Parse soon as well.

This demo shows you how to derive from the existing Kinvey API class (TExtendKinveyAPI = class(TKinveyAPI)) for the Kinvey component and add a new method for executing Kinvey's password reset.

Inside your Kinvey.com account, go to AddOns->Messaging->Email Templates and customize your 'Password Resetemail template. There you can define Sender and Reply To information, the Subject line and the HTML for the body of your email. The App Name referenced in the email is the name of your application you defined inside your Kinvey.com account.



My application consists of 4 edit controls parented to 4 TListBox items:

  • EditUsername

  • EditPassword

  • EditSessionToken

  • EditEmail


TListBox has GroupingKind set to Grouped and StyleLookUp set to 'transparentlistboxstyle'.

I added the KinveyProvider1 component to my form and entered the AppKey, AppSecret and MasterSecret that is displayed inside my Kinvey.com account under 'AppName'->Manage Environments. In order to extend the functionality, I had to add a new method for triggering a password reset email notification which you can see in the code samples below.






Shown: Mobile app running on Windows with Mobile Preview style.

Here is the code for my ExtendKinveyApiUnit


unit ExtendKinveyApiUnit;

interface

uses REST.Backend.Kinveyapi, System.JSON, REST.Client, REST.Types;

type
TExtendKinveyApi = class(TKinveyApi)
private
public
procedure SignupUser(const AUserName, APassword, AEmail: string;
out ALogin: TKinveyApi.TLogin); overload;
procedure PasswordReset(const AEmail: string);
end;

implementation

// New version of signup user that has a password parameter
procedure TExtendKinveyApi.SignupUser(const AUserName, APassword, AEmail: string;
out ALogin: TKinveyApi.TLogin);
var
LJSON: TJSONObject;
begin
LJSON := TJSONObject.Create;
try
LJSON.AddPair('email', AEmail);
inherited SignupUser(AUserName, APassword, LJSON, ALogin);
finally
LJSON.Free;
end;
end;

//POST /rpc/:appKey/:email/user-password-reset-initiate HTTP/1.1
//Host: baas.kinvey.com
//Authorization: [Basic Auth with app credentials]
procedure TExtendKinveyApi.PasswordReset(const AEmail: string);
var
LConnectionInfo: TConnectionInfo;
begin
Request.ResetToDefaults;
// Basic Auth
LConnectionInfo := Self.ConnectionInfo;
LConnectionInfo.UserName := AEmail;
ConnectionInfo := LConnectionInfo;
AddAuthParameter(TAuthentication.UserName);
// App credentials
AddAuthParameter(TAuthentication.AppSecret);
Request.Method := TRESTRequestMethod.rmPOST;
Request.Resource := 'rpc/{appkey}/{email}/user-password-reset-initiate';
Request.AddParameter( 'email', AEmail, TRESTRequestParameterKind.pkURLSEGMENT );
Request.Execute;
CheckForResponseError([201]);
end;

end.

Here is the code for my mobile client


unit KinveyFormUnit;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, IPPeerClient,
REST.OpenSSL, REST.Backend.KinveyProvider, FMX.StdCtrls,
FMX.Edit, ExtendKinveyApiUnit, REST.Backend.ParseProvider, FMX.ListBox,
FMX.Layouts, REST.Backend.ServiceTypes, REST.Backend.MetaTypes, System.JSON,
REST.Backend.KinveyServices, REST.Backend.Providers,
REST.Backend.ServiceComponents;

type
TKinveyForm = class(TForm)
EditUserName: TEdit;
EditPassword: TEdit;
ButtonSignup: TButton;
EditEmail: TEdit;
ButtonPasswordReset: TButton;
EditSessionToken: TEdit;
ToolBar1: TToolBar;
Label5: TLabel;
ListBox1: TListBox;
UserLabel: TListBoxItem;
PasswordLabel: TListBoxItem;
EmailLabel: TListBoxItem;
SessionLabel: TListBoxItem;
KinveyProvider1: TKinveyProvider;
procedure ButtonSignupClick(Sender: TObject);
procedure ButtonPasswordResetClick(Sender: TObject);
procedure FormCreate(Sender: TObject);

private
{ Private declarations }
FApi: TExtendKinveyAPI;
procedure ClearFields;
public
{ Public declarations }
end;

var
KinveyForm: TKinveyForm;

implementation

{$R *.fmx}

uses REST.Backend.KinveyApi;

procedure TKinveyForm.ButtonPasswordResetClick(Sender: TObject);
begin
FApi.PasswordReset(EditEmail.Text);
ShowMessage('Message sent to ' + EditEmail.Text);
end;

procedure TKinveyForm.ButtonSignupClick(Sender: TObject);
var
LLogin: TKinveyAPI.TLogin;
begin
FApi.SignupUser(EditUsername.Text, EditPassword.Text, EditEmail.Text, LLogin);
FApi.Login(LLogin); // Make subsequent calls as this user

EditSessionToken.Text := LLogin.AuthToken;
ShowMessage('Welcome ' + LLogin.User.UserName);
end;

procedure TKinveyForm.FormCreate(Sender: TObject);
begin
FApi := TExtendKinveyAPI.Create(Self);
KinveyProvider1.UpdateApi(FApi);
end;

procedure TKinveyForm.ClearFields;
begin
EditUserName.Text := '';
EditPassword.Text := '';
EditEmail.Text := '';
EditSessionToken.Text := '';

end;

end.

Below you see a screenshot of the email that I received after clicking on the 'Reset Password via Email' button inside my app:



After clicking on the automatically generated reset URL, you see a web based form where you can reset your password:



About
Gold User, Rank: 5, Points: 558
Senior Product Manager, RAD Studio

Comments

  • Guest

    [...] I covered the steps necessary to add password reset email notification functionality to your BaaS enabled Delphi XE6 app using Kinvey. Today, I thought I would explain how to do this [...]

  • Guest
    Charles Stack Wednesday, 23 July 2014

    Thank you, Sarina!

    Somebody asked about this after you previous post - really nice to see you took the challenge and provided a great solution. Your solutions aid in further understanding the cloud components.

    Very cool!

  • Guest
    Mickey Thursday, 24 July 2014

    Hello Sarina,

    Thanks you for this example.

    As I'm using Parse provider, I have adapted your API extension to be Parse REST API compliant.

    Here is the Parse Extension unit - please feel free to publish it if you want:

    -----------------------------------------------------

    unit ParseApiExtension;

    interface

    uses REST.Backend.ParseAPI, System.JSON, REST.Client, REST.Types;

    type
    TParseApiExtension = class(TParseApi)
    private const
    sPasswordReset = 'requestPasswordReset';
    private
    public
    function PasswordReset(const AEmail: string): Boolean;
    end;

    implementation

    //curl -X POST \
    // -H "X-Parse-Application-Id: ${APPLICATION_ID}" \
    // -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
    // -H "Content-Type: application/json" \
    // -d '{"email":"coolguy@iloveapps.com"}' \
    // https://api.parse.com/1/requestPasswordReset
    function TParseApiExtension.PasswordReset(const AEmail: string): Boolean;
    var
    LResponse: TJsonObject;
    LUser: TJSONObject;

    bResult : Boolean;

    begin
    Request.ResetToDefaults;
    // Basic Auth
    AddAuthParameters;
    // App credentials
    Request.Method := TRESTRequestMethod.rmPOST;
    Request.Resource := sPasswordReset;

    try
    LUser := TJSONObject.Create;
    try
    LUser.AddPair('email', AEmail); // Do not localize

    Request.AddBody(LUser);
    Request.Execute;

    CheckForResponseError([201]);

    LResponse := Request.Response.JSONValue as TJSONObject;

    if LResponse.Count = 0 then
    bResult := true;
    finally
    LUser.Free;
    end;
    except
    bResult := false;
    end;

    Result := bResult;
    end;

    end.

    -----------------------------------------------------

    Regards,
    Mickey

  • Guest
    Charles Stack Friday, 25 July 2014

    Thanks Mickey!

  • Guest
    Sarina DuPont Friday, 25 July 2014

    Hi,

    Shortly after I did a post on Kinvey, I also did one for Parse:
    http://blogs.embarcadero.com/sarinadupont/2014/07/23/send-password-reset-emails-by-adding-a-new-baas-method-with-parse/

    Regards,
    Sarina

  • Please login first in order for you to submit comments
  • Page :
  • 1

Check out more tips and tricks in this development video: