Necko:nsIAuthPrompt2: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(killing savePassword, seems essentially unused)
(update per final changes)
 
(14 intermediate revisions by the same user not shown)
Line 14: Line 14:
This suggestion is based on https://bugzilla.mozilla.org/attachment.cgi?id=163161 but slightly modified, and async calls added.
This suggestion is based on https://bugzilla.mozilla.org/attachment.cgi?id=163161 but slightly modified, and async calls added.


  interface nsIAuthPromptCallback : nsISupports {
  /**
  /**
* A object that hold authentication information. The caller of
    * Authentication information is available.
* nsIAuthPrompt2::promptUsernameAndPassword or
    *
* nsIAuthPrompt2::promptPasswordAsync provides an object implementing this
    * @param aContext
* interface; the prompt implementation can then read the values here to prefill
    *       The context as passed to promptPasswordAsync
* the dialog. After the user entered the authentication information, it should
    * @param user
* set the attributes of this object to indicate to the caller what was entered
    *        The username the user entered (or, if ONLY_PASSWORD was set,
* by the user.
    *       that was passed to the nsIAuthPrompt2)
*/
    * @param password
[scriptable, uuid(0d73639c-2a92-4518-9f92-28f71fea5f20)]
    *        The password the user entered.
interface nsIAuthInformation : nsISupports
    * @param domain
{
    *       The domain name the user entered, if NEED_DOMAIN was set.
  /** @name Flags */
    * @param flags
  /* @{ */
    *       Flags as passed to promptPasswordAsync
  /**
    *
  * This dialog belongs to a network host.
    * @note  Any exceptions thrown from this method should be ignored.
  */
    */
  const PRUint32 AUTH_HOST = 1;
  void onAuthAvailable(in nsISupports aContext,
                        in AString user,
                        in AString password,
                        in AString domain,
                        in unsigned long flags);


   /**
  /**
    * Notification that the prompt was cancelled.
   * This dialog belongs to a proxy.
    * @param userCancel
  */
    *       If false, this prompt was cancelled by calling the
  const PRUint32 AUTH_PROXY = 2;
    *       the cancel method on the nsICancelable; otherwise,
 
    *       it was cancelled by the user.
  /**
    */
  * This dialog needs domain information. The user interface should show a
   void onAuthCancelled(in nsISupports aContext,
  * domain field, prefilled with the domain attribute's value.
                        in boolean userCancel);
  */
  const PRUint32 NEED_DOMAIN = 4;
 
  /**
  * This dialog only asks for password information. The implementation SHOULD
  * NOT show a username field. It MUST NOT modify the user attribute,
  * although it should show its initial value to the user in some form. For
  * example, a paragraph in the dialog might say "Please enter your password
  * for user jsmith at server intranet".
  *
  * This flag is mutually exclusive with #NEED_DOMAIN.
  */
  const PRUint32 ONLY_PASSWORD = 8;
  /* @} */
 
  /**
  * Flags describing this dialog. A bitwise OR of the flag values
  * above.
  *
  * It is possible that neither #AUTH_HOST nor #AUTH_PROXY are set.
  *
  * Implementations should ignore flags they don't understand; especially, they
  * should not throw an exception because of an unsupported flag.
  */
  readonly attribute unsigned long flags;
 
  /**
  * The server-supplied realm of the authentication as defined in RFC 2617.
  * Can be the empty string if the protocol does not support realms.
  * Otherwise, this is a human-readable string like "Secret files".
  */
  readonly attribute AString realm;
 
  /**
  * The authentication scheme used for this request, if applicable. If the
  * protocol for this authentication does not support schemes, this will be
  * the empty string. Otherwise, this will be a string such as "basic" or
  * "digest". This string will always be in lowercase.
  */
  readonly attribute AUTF8String authenticationScheme;
 
  /**
  * The initial value should be used to prefill the dialog.
  * Implementations should not show the password in clear.
  * On return, this parameter should contain the username entered by
  * the user.
  */
  attribute AString username;
 
  /**
  * The initial value should be used to prefill the dialog or show it
  * in some other way to the user.
  * On return, this parameter should contain the username entered by
  * the user.
  */
  attribute AString password;
 
  /**
   * The initial value should be used to prefill the dialog or show it
  * in some other way to the user.
  * On return, this parameter should contain the domain entered by
  * the user.
  * This attribute is only used if flags include #NEED_DOMAIN.
  */
  attribute AString domain;
  };
  };


/**
* Interface for callback methods for the asynchronous nsIAuthPrompt2 method.
* Callers MUST call exactly one method if nsIAuthPrompt2::promptPasswordAsync
* returns successfully. They MUST NOT call any method on this interface before
* promptPasswordAsync returns.
*/
[scriptable, uuid(bdc387d7-2d29-4cac-92f1-dd75d786631d)]
interface nsIAuthPromptCallback : nsISupports
{
  /**
  * Authentication information is available.
  *
  * @param aContext
  *        The context as passed to promptPasswordAsync
  * @param aAuthInfo
  *        Authentication information. Must be the same object that was passed
  *        to promptPasswordAsync.
  *
  * @note  Any exceptions thrown from this method should be ignored.
  */
  void onAuthAvailable(in nsISupports aContext,
                      in nsIAuthInformation aAuthInfo);
  /**
  * Notification that the prompt was cancelled.
  *
  * @param aContext
  *        The context that was passed to promptPasswordAsync.
  * @param userCancel
  *        If false, this prompt was cancelled by calling the
  *        the cancel method on the nsICancelable; otherwise,
  *        it was cancelled by the user.
  */
  void onAuthCancelled(in nsISupports aContext, in boolean userCancel);
};
/**
* An interface allowing to prompt for a username and password. This interface
* is usually acquired using getInterface on notification callbacks or similar.
* It can be used to prompt users for authentication information, either
* synchronously or asynchronously.
*/
[scriptable, uuid(447fc780-1d28-412a-91a1-466d48129c65)]
  interface nsIAuthPrompt2 : nsISupports
  interface nsIAuthPrompt2 : nsISupports
  {         
  {         
    /** @name Security Levels */
  /** @name Security Levels */
    /* @{ */
  /* @{ */
    /**
  /**
    * The password will be sent unencrypted. No security provided.
  * The password will be sent unencrypted. No security provided.
    */
  */
    const PRUint32 LEVEL_NONE = 0;
  const PRUint32 LEVEL_NONE = 0;
    /**
  /**
    * Password will be sent encrypted, but the connection is otherwise
  * Password will be sent encrypted, but the connection is otherwise
    * insecure.
  * insecure.
    */
  */
    const PRUint32 LEVEL_PW_ENCRYPTED = 1;
  const PRUint32 LEVEL_PW_ENCRYPTED = 1;
    /**
  /**
    * The connection, both for password and data, is secure.
  * The connection, both for password and data, is secure.
    */
  */
    const PRUint32 LEVEL_SECURE = 2;
  const PRUint32 LEVEL_SECURE = 2;
    /* @} */
  /* @} */


    /** @name Flags */
  /**
    /* @{ */
  * Requests a username and a password. Implementations will commonly show a
    /**
  * dialog with a username and password field, depending on flags also a
    * This dialog belongs to a network host.
  * domain field.
    */
  *
    const PRUint32 AUTH_HOST = 0;
  * @param aChannel
    /**
  *        The channel that requires authentication.
    * This dialog belongs to a proxy.
  * @param level
    */
  *        One of the level constants from above. See there for descriptions
    const PRUint32 AUTH_PROXY = 1;
  *        of the levels.
  * @param authInfo
  *        Authentication information object. The implementation should fill in
  *        this object with the information entered by the user before
  *       returning.
  *
  * @retval true
  *         Authentication can proceed using the values in the authInfo
  *        object.
  * @retval false
  *        Authentication should be cancelled, usually because the user did
  *        not provide username/password.
  *
  * @note  Exceptions thrown from this function will be treated like a
  *         return value of false.
  */
  boolean promptAuth(in nsIChannel aChannel,
                    in PRUint32 level,
                    in nsIAuthInformation authInfo);


    /**
  /**
    * This dialog needs domain information. The user interface should show a
  * Asynchronously prompt the user for a username and password.
    * domain field, prefilled with the aDomain paramter's value.
  * This has largely the same semantics as promptUsernameAndPassword(),
    */
  * but must return immediately after calling and return the entered
    const PRUint32 NEED_DOMAIN = 2;
  * data in a callback.
  *
  * If the user closes the dialog using a cancel button or similar,
  * the callback's nsIAuthPromptCallback::onAuthCancelled method must be
  * called.
  * Calling nsICancelable::cancel on the returned object SHOULD close the
  * dialog and MUST call nsIAuthPromptCallback::onAuthCancelled on the provided
  * callback.
  *
  * @throw NS_ERROR_NOT_IMPLEMENTED
  *        Asynchronous authentication prompts are not supported;
  *        the caller should fall back to promptUsernameAndPassword().
  */
  nsICancelable asyncPromptAuth(in nsIChannel aChannel,
                                in nsIAuthPromptCallback aCallback,
                                in nsISupports aContext,
                                in PRUint32 level,
                                in nsIAuthInformation authInfo);
};


    /**
    * This dialog only asks for password information. The implementation SHOULD
    * NOT show a username field. It MUST NOT modify the user inout parameter,
    * although it should show its initial value to the user in some form. For
    * example, a paragraph in the dialog might say "Please enter your password
    * for user jsmith at server intranet".
    *
    * This flag is mutually exclusive with NEED_DOMAIN.
    */
    const PRUint32 ONLY_PASSWORD = 4;
    /* @} */


    /**
    * Requests a username and a password. Implementations will commonly show a
    * dialog with a username and password field, depending on flags also a
    * domain field.
    *
    * @param aChannel
    *        The channel that requires authentication.
    * @param passwordRealm
    *        The server-supplied realm for the password. This is a
    *        human-readable string like "Secret files".
    * @param level
    *        One of the level constants from above. See there for descriptions
    *        of the levels.
    * @param flags
    *        Flags describing this dialog. A bitwise OR of the flag values
    *        above.
    * @param user
    *        The initial value should be used to prefill the dialog.
    *        Implementations should not show the password in clear.
    *        On return, this parameter should contain the username entered by
    *        the user.
    * @param pwd
    *        The initial value should be used to prefill the dialog or show it
    *        in some other way to the user.
    *        On return, this parameter should contain the username entered by
    *        the user.
    * @param domain
    *        The initial value should be used to prefill the dialog or show it
    *        in some other way to the user.
    *        On return, this parameter should contain the domain entered by
    *        the user.
    *        This parameter is only used if flags include AUTH_DOMAIN.
    *
    * @retval true
    *        Authentication can proceed using the values of the out
    *        parameters.
    * @retval false
    *        Authentication should be cancelled, usually because the user did
    *        not provide username/password.
    *
    * @note  Exceptions thrown from this function will be treated like a
    *        return value of false.
    */
    boolean promptUsernameAndPassword(in nsIChannel aChannel,
                                      in AString passwordRealm,
                                      in PRUint32 level,
                                      in PRUint32 flags,
                                      inout AString user,
                                      inout AString pwd,
                                      inout AString domain);


    /**
    * Asynchronously prompt the user for a username and password.
    * This has largely the same semantics as promptUsernameAndPassword,
    * but must return immediately after calling and return the entered
    * data in a callback.
    *
    * If the user closes the dialog using a cancel button or similar,
    * the callback's onAuthCancelled method must be called.
    * Calling cancel on the returned object SHOULD close the dialog
    * and MUST call onAuthCancelled on the provided callback.
    *
    * @throw NS_ERROR_NOT_IMPLEMENTED
    *        Asynchronous authentication prompts are not supported;
    *        the caller should fall back to promptUsernameAndPassword
    */
    nsICancelable promptPasswordAsync(in nsIChannel aChannel,
                                      in nsIAuthPromptCallback aCallback,
                                      in nsISupports aContext,
                                      in PRUint32 level,
                                      in PRUint32 flags,
                                      in AString user,
                                      in AString pwd,
                                      in AString domain);
};


== Issues ==
== Issues ==
Line 180: Line 233:
** However, after thinking more about this, I don't think it makes sense for this interface to be used by PSM. PSM has no use for a user or a domain, the "levels" here are not useful for it, and dialogs for certificate stores will probably look quite different. It should have its own interface.
** However, after thinking more about this, I don't think it makes sense for this interface to be used by PSM. PSM has no use for a user or a domain, the "levels" here are not useful for it, and dialogs for certificate stores will probably look quite different. It should have its own interface.
* Use nsIRequest instead of nsIChannel?
* Use nsIRequest instead of nsIChannel?
** SOCKS authentication on a raw socket might be a use case
** But nsIRequest has no obvious place to get something remotely URI-like
* The parameter lists are quite long; group some of the info together on an object? This object could be passed to both functions.
* The parameter lists are quite long; group some of the info together on an object? This object could be passed to both functions.
** It would fix this error: ../../../../../mozilla/netwerk/base/public/nsIAuthPrompt2.idl:106: Error: [domstring], [utf8string], [cstring], [astring] types cannot be used as inout parameters
** It would fix this error: ../../../../../mozilla/netwerk/base/public/nsIAuthPrompt2.idl:106: Error: [domstring], [utf8string], [cstring], [astring] types cannot be used as inout parameters
** switched to that in the interfaces above
* mention threads in the docs
* what's "LEVEL_SECURE"?
* maybe nsIAuthInformation could have a parameter filled on return for how long to allow caching of auth info
== Reasonings ==
This lists some reasons for why some parts of the interface look like they do
* nsIChannel as opposed to nsIURI allows inspecting the securityInfo of the channel to determine the quality of the SSL encryption
* Added authenticationScheme (RFC 2617 wording) to nsIAuthInformation to provide more information to the impl (they can always ignore the field if they don't care). this will be basic, digest, etc.
** The level is still useful, for SSL and for not requiring the impl to understand all possible schemes, and also for non-HTTP protocols
= Wallet/Satchel =
These want to add a checkbox to the dialog. I propose an interface like this:
/**
  * This interface allows creating auth prompts that have a specific parent.
  */
[scriptable, uuid(...)]
interface nsIPromptFactory
{
  /**
  * Returns an object implementing the specified interface that creates
  * prompts parented to aParent.
  */
  void getPrompt(in nsIDOMWindow aParent, in nsIIDRef iid,
                [iid_is(iid),retval] out nsQIResult result);
};
This allows more flexibility than the current interface that wraps an nsIPrompt.
For actually adding the checkbox, nsIPromptService2 will need a method like promptUsernameAndPassword2Checkbox (I decided on naming it promptAuth)

Latest revision as of 21:34, 26 August 2006

https://bugzilla.mozilla.org/show_bug.cgi?id=265780

This page describes new and improved authentication interfaces for necko. There are various downsides of the current ones, including:

The interfaces in question are nsIAuthPrompt and nsIPromptService; possibly nsIPrompt as well.

I'll suggest an nsIAuthPrompt2 interface below. Its methods will have counterparts in nsIPromptService2; they will have the same signature but an additional window argument.

The nsIAuthPrompt2 is what necko calls stuff on; nsIPromptService2 is what embeddors would implement.

This suggestion is based on https://bugzilla.mozilla.org/attachment.cgi?id=163161 but slightly modified, and async calls added.

/**
* A object that hold authentication information. The caller of
* nsIAuthPrompt2::promptUsernameAndPassword or
* nsIAuthPrompt2::promptPasswordAsync provides an object implementing this
* interface; the prompt implementation can then read the values here to prefill
* the dialog. After the user entered the authentication information, it should
* set the attributes of this object to indicate to the caller what was entered
* by the user.
*/
[scriptable, uuid(0d73639c-2a92-4518-9f92-28f71fea5f20)]
interface nsIAuthInformation : nsISupports
{
 /** @name Flags */
 /* @{ */
 /**
  * This dialog belongs to a network host.
  */
 const PRUint32 AUTH_HOST = 1;
 /**
  * This dialog belongs to a proxy.
  */
 const PRUint32 AUTH_PROXY = 2;
 /**
  * This dialog needs domain information. The user interface should show a
  * domain field, prefilled with the domain attribute's value.
  */
 const PRUint32 NEED_DOMAIN = 4;
 /**
  * This dialog only asks for password information. The implementation SHOULD
  * NOT show a username field. It MUST NOT modify the user attribute,
  * although it should show its initial value to the user in some form. For
  * example, a paragraph in the dialog might say "Please enter your password
  * for user jsmith at server intranet".
  *
  * This flag is mutually exclusive with #NEED_DOMAIN.
  */
 const PRUint32 ONLY_PASSWORD = 8;
 /* @} */
 /**
  * Flags describing this dialog. A bitwise OR of the flag values
  * above.
  *
  * It is possible that neither #AUTH_HOST nor #AUTH_PROXY are set.
  *
  * Implementations should ignore flags they don't understand; especially, they
  * should not throw an exception because of an unsupported flag.
  */
 readonly attribute unsigned long flags;
 /**
  * The server-supplied realm of the authentication as defined in RFC 2617.
  * Can be the empty string if the protocol does not support realms.
  * Otherwise, this is a human-readable string like "Secret files".
  */
 readonly attribute AString realm;
 /**
  * The authentication scheme used for this request, if applicable. If the
  * protocol for this authentication does not support schemes, this will be
  * the empty string. Otherwise, this will be a string such as "basic" or 
  * "digest". This string will always be in lowercase.
  */
 readonly attribute AUTF8String authenticationScheme;
 /**
  * The initial value should be used to prefill the dialog.
  * Implementations should not show the password in clear.
  * On return, this parameter should contain the username entered by
  * the user.
  */
 attribute AString username;
 /**
  * The initial value should be used to prefill the dialog or show it
  * in some other way to the user.
  * On return, this parameter should contain the username entered by
  * the user.
  */
 attribute AString password;
 /**
  * The initial value should be used to prefill the dialog or show it
  * in some other way to the user.
  * On return, this parameter should contain the domain entered by
  * the user.
  * This attribute is only used if flags include #NEED_DOMAIN.
  */
 attribute AString domain;
};
/**
* Interface for callback methods for the asynchronous nsIAuthPrompt2 method.
* Callers MUST call exactly one method if nsIAuthPrompt2::promptPasswordAsync
* returns successfully. They MUST NOT call any method on this interface before
* promptPasswordAsync returns.
*/
[scriptable, uuid(bdc387d7-2d29-4cac-92f1-dd75d786631d)]
interface nsIAuthPromptCallback : nsISupports
{
 /**
  * Authentication information is available.
  *
  * @param aContext
  *        The context as passed to promptPasswordAsync
  * @param aAuthInfo
  *        Authentication information. Must be the same object that was passed
  *        to promptPasswordAsync.
  *
  * @note  Any exceptions thrown from this method should be ignored.
  */
 void onAuthAvailable(in nsISupports aContext,
                      in nsIAuthInformation aAuthInfo);
 /**
  * Notification that the prompt was cancelled.
  *
  * @param aContext
  *        The context that was passed to promptPasswordAsync.
  * @param userCancel
  *        If false, this prompt was cancelled by calling the
  *        the cancel method on the nsICancelable; otherwise,
  *        it was cancelled by the user.
  */
 void onAuthCancelled(in nsISupports aContext, in boolean userCancel);
};


/**
* An interface allowing to prompt for a username and password. This interface
* is usually acquired using getInterface on notification callbacks or similar.
* It can be used to prompt users for authentication information, either
* synchronously or asynchronously.
*/
[scriptable, uuid(447fc780-1d28-412a-91a1-466d48129c65)]
interface nsIAuthPrompt2 : nsISupports
{         
 /** @name Security Levels */
 /* @{ */
 /**
  * The password will be sent unencrypted. No security provided.
  */
 const PRUint32 LEVEL_NONE = 0;
 /**
  * Password will be sent encrypted, but the connection is otherwise
  * insecure.
  */
 const PRUint32 LEVEL_PW_ENCRYPTED = 1;
 /**
  * The connection, both for password and data, is secure.
  */
 const PRUint32 LEVEL_SECURE = 2;
 /* @} */
 /**
  * Requests a username and a password. Implementations will commonly show a
  * dialog with a username and password field, depending on flags also a
  * domain field.
  *
  * @param aChannel
  *        The channel that requires authentication.
  * @param level
  *        One of the level constants from above. See there for descriptions
  *        of the levels.
  * @param authInfo
  *        Authentication information object. The implementation should fill in
  *        this object with the information entered by the user before
  *        returning.
  *
  * @retval true
  *         Authentication can proceed using the values in the authInfo
  *         object.
  * @retval false
  *         Authentication should be cancelled, usually because the user did
  *         not provide username/password.
  *
  * @note   Exceptions thrown from this function will be treated like a
  *         return value of false.
  */
 boolean promptAuth(in nsIChannel aChannel,
                    in PRUint32 level,
                    in nsIAuthInformation authInfo);
 /**
  * Asynchronously prompt the user for a username and password.
  * This has largely the same semantics as promptUsernameAndPassword(),
  * but must return immediately after calling and return the entered
  * data in a callback.
  *
  * If the user closes the dialog using a cancel button or similar,
  * the callback's nsIAuthPromptCallback::onAuthCancelled method must be
  * called.
  * Calling nsICancelable::cancel on the returned object SHOULD close the
  * dialog and MUST call nsIAuthPromptCallback::onAuthCancelled on the provided
  * callback.
  *
  * @throw NS_ERROR_NOT_IMPLEMENTED
  *        Asynchronous authentication prompts are not supported;
  *        the caller should fall back to promptUsernameAndPassword().
  */
 nsICancelable asyncPromptAuth(in nsIChannel aChannel,
                               in nsIAuthPromptCallback aCallback,
                               in nsISupports aContext,
                               in PRUint32 level,
                               in nsIAuthInformation authInfo);
};



Issues

  • NSS/PSM wants to prompt for passwords as well, and has no nsIChannel available
    • http://lxr.mozilla.org/seamonkey/source/security/manager/ssl/src/nsNSSCallbacks.cpp#188
    • Make aChannel an nsISupports, which can also be a certificate or certificate store or whatever?
    • However, after thinking more about this, I don't think it makes sense for this interface to be used by PSM. PSM has no use for a user or a domain, the "levels" here are not useful for it, and dialogs for certificate stores will probably look quite different. It should have its own interface.
  • Use nsIRequest instead of nsIChannel?
    • SOCKS authentication on a raw socket might be a use case
    • But nsIRequest has no obvious place to get something remotely URI-like
  • The parameter lists are quite long; group some of the info together on an object? This object could be passed to both functions.
    • It would fix this error: ../../../../../mozilla/netwerk/base/public/nsIAuthPrompt2.idl:106: Error: [domstring], [utf8string], [cstring], [astring] types cannot be used as inout parameters
    • switched to that in the interfaces above
  • mention threads in the docs
  • what's "LEVEL_SECURE"?
  • maybe nsIAuthInformation could have a parameter filled on return for how long to allow caching of auth info

Reasonings

This lists some reasons for why some parts of the interface look like they do

  • nsIChannel as opposed to nsIURI allows inspecting the securityInfo of the channel to determine the quality of the SSL encryption
  • Added authenticationScheme (RFC 2617 wording) to nsIAuthInformation to provide more information to the impl (they can always ignore the field if they don't care). this will be basic, digest, etc.
    • The level is still useful, for SSL and for not requiring the impl to understand all possible schemes, and also for non-HTTP protocols

Wallet/Satchel

These want to add a checkbox to the dialog. I propose an interface like this:

/**
 * This interface allows creating auth prompts that have a specific parent.
 */
[scriptable, uuid(...)]
interface nsIPromptFactory
{
 /**
  * Returns an object implementing the specified interface that creates
  * prompts parented to aParent.
  */
 void getPrompt(in nsIDOMWindow aParent, in nsIIDRef iid,
                [iid_is(iid),retval] out nsQIResult result);
};

This allows more flexibility than the current interface that wraps an nsIPrompt.

For actually adding the checkbox, nsIPromptService2 will need a method like promptUsernameAndPassword2Checkbox (I decided on naming it promptAuth)