def METHOD_NAME(self, storageName, s3_method, urls, expiration):
    """Generate a presigned URL for a given object, given method, and given storage
    Permissions are checked against the DFC
    :param storageName: SE name
    :param s3_method: name of the S3 client method we want to perform.
    :param urls: Iterable of urls. If s3_method is put_object, it must be a dict <url:fields> where fields
                 is a dictionary (see ~DIRAC.Resources.Storage.S3Storage.S3Storage.createPresignedUrl)
    :param expiration: duration of the token
    """
    log = LOG.getSubLogger("createPresignedUrl")
    if s3_method == "put_object" and not isinstance(urls, dict):
        return S_ERROR(errno.EINVAL, "urls has to be a dict <url:fields>")
    # Fetch the remote credentials, and set them in the ThreadConfig
    # This allows to perform the FC operations on behalf of the user
    credDict = self.getRemoteCredentials()
    if not credDict:
        # If we can't obtain remote credentials, consider it permission denied
        return S_ERROR(errno.EACCES, "Could not obtain remote credentials")
    self._tc.setDN(credDict["DN"])
    self._tc.setGroup(credDict["group"])
    successful = {}
    failed = {}
    s3Plugin = self._S3Storages[storageName]
    for url in urls:
        try:
            log.verbose(
                "Creating presigned URL",
                f"SE: {storageName} Method: {s3_method} URL: {url} Expiration: {expiration}",
            )
            # Finding the LFN to query the FC
            # I absolutely hate doing such path mangling but well....
            res = s3Plugin._getKeyFromURL(url)  # pylint: disable=protected-access
            if not res["OK"]:
                failed[url] = res["Message"]
                log.debug(f"Could not parse the url {url} {res}")
                continue
            lfn = "/" + res["Value"]
            log.debug(f"URL: {url} -> LFN {lfn}")
            # Checking whether access is permitted
            res = self._hasAccess(lfn, s3_method)
            if not res["OK"]:
                failed[url] = res["Message"]
                continue
            if not res["Value"]:
                failed[url] = "Permission denied"
                continue
            res = returnSingleResult(
                s3Plugin.createPresignedUrl({url: urls.get("Fields")}, s3_method, expiration=expiration)
            )
            log.debug(f"Presigned URL for {url}: {res}")
            if res["OK"]:
                successful[url] = res["Value"]
            else:
                failed["url"] = res["Message"]
        except Exception as e:
            log.exception("Exception presigning URL")
            failed[url] = repr(e)
    return S_OK({"Successful": successful, "Failed": failed})