|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +--- |
| 4 | + |
| 5 | +# Authenticating against a server |
| 6 | + |
| 7 | +One of the big issues you have to deal with when working with with |
| 8 | +other people using Git is authenticating to the server you want to |
| 9 | +fetch from or push to. In this post we'll explore how libgit2 deals |
| 10 | +with presenting the different authentication possibilities across |
| 11 | +transport and platforms. |
| 12 | + |
| 13 | +The first place where you can specify the username and password to use |
| 14 | +is in the URL. This can be useful in cases where these are always |
| 15 | +known, e.g. in specialised scripts which perform some very specific |
| 16 | +task. For most uses, however, you do want the ability to specify the |
| 17 | +the username and password (or keypair) during the request. An |
| 18 | +application might want to even go and ask the human sitting at the |
| 19 | +computer for the credentials to the server or it might retrieve the |
| 20 | +credentials from its own storage area. To handle this cases, you need |
| 21 | +to specify a callback in order for libgit2 to be able to call your |
| 22 | +code when it needs to find out about the user's credentials. |
| 23 | + |
| 24 | +The callback is provided via the `credentials` field in the |
| 25 | +`git_remote_callbacks` structure. This structure is embedded in both |
| 26 | +`git_fetch_options` and `git_push_options` so you can specify it both |
| 27 | +both operations. |
| 28 | + |
| 29 | +When libgit2 connects to the server, it may ask for the user's |
| 30 | +credentials before performing the operation (this is always the case |
| 31 | +for SSH). libgit2 will try to get the information from two places: |
| 32 | + |
| 33 | +1. The URL. If there is a username/password combination in it, it will |
| 34 | + try to use that first. For SSH, it will use that username during |
| 35 | + the initial query as well. |
| 36 | +2. The caller-provided credentials callback. This callback gets the |
| 37 | + url and the username from the URL. This can be used to pre-fill a |
| 38 | + dialog with the data already in the URL. |
| 39 | + |
| 40 | +If the server doesn't accept the credentials from the callback, it |
| 41 | +will be called again. The callback drives the authentication loop. It |
| 42 | +will get called until it returns credentials accepted by the server or |
| 43 | +it returns an error code. |
| 44 | + |
| 45 | +If the connection is over SSH, libgit2 needs to know which username |
| 46 | +will be used before it can know which authentication methods are |
| 47 | +available. If one is not provided on the URL, libgit2 will ask the |
| 48 | +credentials callback as well, with a supported credential type of |
| 49 | +`GIT_CREDTYPE_USERNAME`. libgit2 can then query the server for which |
| 50 | +authentication types it supports and will call the credentials |
| 51 | +callback again with those types. SSH servers won't allow a username to |
| 52 | +be changed within one session, so the username in the URL or provided |
| 53 | +in the callback must be the one which is used for whichever |
| 54 | +credentials are returned (the RFC leaves this open, but servers in |
| 55 | +practice behave this way). |
| 56 | + |
| 57 | +The credentials are returned using the same pattern which libgit2 uses |
| 58 | +for its API: the first parameter is an output parameter and the `int` |
| 59 | +return value determines success or failure. A typicall callback would |
| 60 | +hand off control to the UI (or other retrieval method) to gather |
| 61 | +information and then chain the return code to one of the credential |
| 62 | +object's constructors. For example, if an application is only |
| 63 | +interested in supporting user/password authentication, it can do something like: |
| 64 | + |
| 65 | +```C |
| 66 | +int credentials_cb(git_cred **out, const char *url, const char *username_from_url, |
| 67 | + unsigned int allowed_types, void *payload) |
| 68 | +{ |
| 69 | + int error; |
| 70 | + const char *user, *pass; |
| 71 | + |
| 72 | + /* |
| 73 | + * Ask the user via the UI. On error, store the information and return GIT_EUSER which will be |
| 74 | + * bubbled up to the code performing the fetch or push. Using GIT_EUSER allows the application |
| 75 | + * to know it was an error from the application instead of libgit2. |
| 76 | + */ |
| 77 | + if ((error = ask_user(&user, &pass, url, username_from_url, allowed_types)) < 0) { |
| 78 | + store_error(error); |
| 79 | + return GIT_EUSER; |
| 80 | + } |
| 81 | + |
| 82 | + return git_cred_plaintext_new(out, user, pass); |
| 83 | +} |
| 84 | +``` |
0 commit comments