Facing verification failed issue and found many similar issues on StackExchange but couldn't solve my problem so posting here.

I have deployed a Rust contract on devnet. It has an instruction which invokes spl_token transfer 
 user's token account to the my contract's token account.

When I call the contract instruction from frontend, the signature verification fails after approve popup from wallet: 
{"code":-32003,"message":"failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account"}

Here is the Rust code:
    

    let transfer_to_initializer_ix = spl_token::instruction::transfer(
            token_program.key,
            source_token_account.key,
            destination_token_account.key,
            initializer.key,
            &[],
            1,
        )?;
        msg!("Calling token program to transfer tokens");
        invoke(
            &transfer_to_initializer_ix,
            &[
                source_token_account.clone(),
                destination_token_account.clone(),
                initializer.clone(),
                token_program.clone(),
            ]
        )?;

This is how I send the call to instruction from my react app:

    const instruction = new web3.TransactionInstruction({
                keys: [
                    {
                        pubkey: publicKey,
                        isSigner: true,
                        isWritable: false,
                    },
                    {
                        pubkey: pda,
                        isSigner: false,
                        isWritable: true
                    },
                    {
                        isSigner: false,
                        isWritable: true,
                        pubkey: web3.SystemProgram.programId
                    },
                    {
                        is_signer: false,
                        is_writable: true,
                        pubkey: userAta,
                    },
                    {
                        is_signer: false,
                        is_writable: true,
                        pubkey: crowdpadATA,
                    },
                    {
                        is_signer: false,
                        is_writable: false,
                        pubkey: token.TOKEN_PROGRAM_ID,
                    },
                ],
                data: buffer,
                programId: crowdpadStakingProgram
            })
    
            console.log('adding staking instruction')
            transaction.add(instruction)
    
            try {
                const txid = await sendTransaction(transaction, connection);
    
                alert(`Transaction submitted: https://explorer.solana.com/tx/${txid}?cluster=devnet`)
                console.log(`Transaction submitted: https://explorer.solana.com/tx/${txid}?cluster=devnet`)
            } catch (e) {
                console.log(JSON.stringify(e))
                alert(JSON.stringify(e))
            }
        }
I checked the documentation and also discussed the issue with peers. Unfortunately the issue persisted. All help is appreciated!