HTTPS/Authenticated

Revision as of 15:24, 19 January 2020 by rosettacode>WolfgangEnzinger (→‎{{header|Visual Basic}}: Added support for TLS 1.2)

The goal of this task is to demonstrate HTTPS requests with authentication. Implementations of this task should not use client certificates for this: that is the subject of another task.

Task
HTTPS/Authenticated
You are encouraged to solve this task according to the task description, using any language you may know.

AutoHotkey

Library: iweb
Library: COM

<lang AutoHotkey>iWeb_Init() pwb := iWeb_newGui(0, 0, 1000, 800) iWeb_nav(pwb, "http://www.facebook.com/login.php?ref=pf") iWeb_Term() iWeb_complete(pwb) inputbox, email, email inputbox, pass, password iWeb_setDomObj(pwb,"Email",email) iWeb_setDomObj(pwb,"pass",pass) iWeb_clickDomObj(pwb, "login") return

  1. Include iweb.ahk
  2. Include COM.ahk
  3. Include COMinvokeDeep.ahk</lang>

C

Library: libcurl

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include "curl/curl.h"

int main(void) {

       CURL *curl;
       char buffer[CURL_ERROR_SIZE];
       if ((curl = curl_easy_init()) != NULL) {
               curl_easy_setopt(curl, CURLOPT_URL, "https://user:password@secure.example.com/");
               curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
               curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, buffer);
               if (curl_easy_perform(curl) != CURLE_OK) {
                       fprintf(stderr, "%s\n", buffer);
                       return EXIT_FAILURE;
               }
               curl_easy_cleanup(curl);
       }
       return EXIT_SUCCESS;

}</lang>

C#

Works with: C sharp version 3.0

<lang csharp> using System; using System.Net;

class Program {

   static void Main(string[] args)
   {
       var client = new WebClient();
       // credentials of current user:
       client.Credentials = CredentialCache.DefaultCredentials;
       // or specify credentials manually:
       client.Credentials = new NetworkCredential("User", "Password");
       var data = client.DownloadString("https://example.com");
       Console.WriteLine(data);
   }

} </lang>

Clojure

Library: clj-http

<lang clojure>(clj-http.client/get "https://somedomain.com"

                    {:basic-auth ["user" "pass"]})</lang>

Delphi

<lang Delphi>program ShowHTTPSAuthenticated;

{$APPTYPE CONSOLE}

uses IdHttp, IdSSLOpenSSL;

var

 s: string;
 lHTTP: TIdHTTP;
 lIOHandler: TIdSSLIOHandlerSocketOpenSSL;

begin

 ReportMemoryLeaksOnShutdown := True;
 lHTTP := TIdHTTP.Create(nil);
 lIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
 try
   lHTTP.Request.Username := 'USERNAME';
   lHTTP.Request.Password := 'PASSWD';
   lHTTP.IOHandler := lIOHandler;
   lHTTP.HandleRedirects := True;
   s := lHTTP.Get('https://SomeSecureSite.net/');
   Writeln(s);
 finally
   lHTTP.Free;
   lIOHandler.Free;
 end;

end.</lang>

Go

The task solution is really the client program, but to test it I wrote a server and created a custom certificate. I won't describe the certificate, but this is the server: <lang go>package main

import (

   "encoding/base64"
   "io"
   "log"
   "net/http"
   "strings"

)

const userPass = "rosetta:code" const unauth = http.StatusUnauthorized

func hw(w http.ResponseWriter, req *http.Request) {

   auth := req.Header.Get("Authorization")
   if !strings.HasPrefix(auth, "Basic ") {
       log.Print("Invalid authorization:", auth)
       http.Error(w, http.StatusText(unauth), unauth)
       return
   }
   up, err := base64.StdEncoding.DecodeString(auth[6:])
   if err != nil {
       log.Print("authorization decode error:", err)
       http.Error(w, http.StatusText(unauth), unauth)
       return
   }
   if string(up) != userPass {
       log.Print("invalid username:password:", string(up))
       http.Error(w, http.StatusText(unauth), unauth)
       return
   }
   io.WriteString(w, "Goodbye, World!")

}

func main() {

   http.HandleFunc("/", hw)
   log.Fatal(http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil))

}</lang> It is a "Hello world" server, but over TLS and with basic authentication required on the Get. Errors are logged to aid client debugging.

The client: <lang go>package main

import (

   "crypto/tls"
   "crypto/x509"
   "fmt"
   "io/ioutil"
   "log"
   "net/http"

)

const (

   userid   = "rosetta"
   password = "code"

)

func main() {

   // Use custom certificate for testing.  Not exactly required by task.
   b, err := ioutil.ReadFile("cert.pem")
   if err != nil {
       log.Fatal(err)
   }
   pool := x509.NewCertPool()
   if ok := pool.AppendCertsFromPEM(b); !ok {
       log.Fatal("Failed to append cert")
   }
   tc := &tls.Config{RootCAs: pool}
   tr := &http.Transport{TLSClientConfig: tc}
   client := &http.Client{Transport: tr}
   req, err := http.NewRequest("GET", "https://127.0.0.1:8080", nil)
   if err != nil {
       log.Fatal(err)
   }
   // This one line implements the authentication required for the task.
   req.SetBasicAuth(userid, password)
   // Make request and show output.
   resp, err := client.Do(req)
   if err != nil {
       log.Fatal(err)
   }
   b, err = ioutil.ReadAll(resp.Body)
   resp.Body.Close()
   if err != nil {
       log.Fatal(err)
   }
   fmt.Println(string(b))

}</lang>

Haskell

Example uses the req and aeson packages:

<lang haskell>{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import Data.Aeson (Value) import Data.Default.Class (def) import Network.HTTP.Req

                   ( (/:)
                   , GET(..)
                   , NoReqBody(..)
                   , basicAuth
                   , https
                   , jsonResponse
                   , req
                   , responseBody
                   , runReq
                   )

main :: IO () main = do

   response <- runReq def $ req
           GET
           (https "httpbin.org" /: "basic-auth" /: "someuser" /: "somepassword")
           NoReqBody
           jsonResponse
           (basicAuth "someuser" "somepassword")
   print (responseBody response :: Value)</lang>

Julia

An example using HTTP (see the source for HTTP.jl for the code below ) to access and play a song: <lang Julia> using HTTP, HTTP.IOExtras, JSON, MusicProcessing HTTP.open("POST", "http://music.com/play") do io

   write(io, JSON.json([
       "auth" => "12345XXXX",
       "song_id" => 7,
   ]))
   r = startread(io)
   @show r.status
   while !eof(io)
       bytes = readavailable(io)
       play(bytes)
   end

end </lang>


Kotlin

<lang scala>// version 1.2.0

import java.net.Authenticator import java.net.PasswordAuthentication import javax.net.ssl.HttpsURLConnection import java.net.URL import java.io.InputStreamReader import java.io.BufferedReader

object PasswordAuthenticator : Authenticator() {

   override fun getPasswordAuthentication() =
       PasswordAuthentication ("username", "password".toCharArray())

}

fun main(args: Array<String>) {

   val url = URL("https://somehost.com")
   val con = url.openConnection() as HttpsURLConnection
   Authenticator.setDefault(PasswordAuthenticator)
   con.allowUserInteraction = true
   con.connect()
   val isr = InputStreamReader(con.inputStream)
   val br = BufferedReader(isr)
   while (true) {
       val line = br.readLine()
       if (line == null) break
       println(line)
   }

}</lang>

Lasso

<lang Lasso>local(username = 'hello',password = 'world') local(x = curl('https://sourceforge.net'))

  1. x->set(CURLOPT_USERPWD, #username + ':' + #password)

local(y = #x->result)

  1. y->asString</lang>

LiveCode

HTTP Basic Auth as part of url <lang LiveCode>command getAuthWebResource

   libURLFollowHttpRedirects true
   libURLSetSSLVerification true
   put URL "https://user:passwd@example.basicauth.com/" into response
   put response

end getAuthWebResource</lang>

You can also set the headers for the basic auth requests <lang LiveCode>command getAuthWebResource

   libURLFollowHttpRedirects true
   libURLSetSSLVerification true
   set the httpHeaders to "Authorization: Basic " && base64Encode("user:passwd")
   put URL "https://example.basicauth.com" into response
   put response

end getAuthWebResource</lang>

Lua

Works with: Lua version 5.1 - 5.3
Library: lua-requests

<lang lua> local requests = require('requests') local auth = requests.HTTPBasicAuth('admin', 'admin') local resp, e = requests.get({

 url = 'https://httpbin.org/basic-auth/admin/admin',
 auth = auth

}) io.write(string.format('Status: %d', resp.status_code)) </lang>

Output:
Status: 200

Mathematica / Wolfram Language

<lang Mathematica>a = RunThrough["curl -u JohnDoe:Password https://www.example.com", 1] For[ i=0, i < Length[a] , i++, SomeFunction[a]]</lang>

Perl

Library: LWP

<lang perl>use LWP::UserAgent qw(); my $ua = LWP::UserAgent->new; my $netloc = 'http://www.buddhism-dict.net/cgi-bin/xpr-dealt.pl:80'; $ua->credentials(

  $netloc,
  'CJK-E and Buddhist Dictionaries', # basic realm
  'guest',  # user
  ,       # empty pw

); my $response = $ua->get($netloc);

use WWW::Mechanize qw(); my $mech = WWW::Mechanize->new; $mech->get('https://login.yahoo.com/'); $mech->submit_form(with_fields => {

   login         => 'XXXXXX',
   passwd        => 'YYYYYY',
   '.persistent' => 'y',  # tick checkbox

});</lang>

Perl 6

Works with: Rakudo version 2017.09

Used here to connect to my local wireless router to a page that is password protected. Obviously not going to be generally publicly accessible but should be easily adaptable to other sites / devices.

<lang perl6>use HTTP::UserAgent;

my $username = 'username'; # my username my $password = 'password'; # my password my $address = 'http://192.168.1.1/Status_Router.asp'; # my local wireless router

my $ua = HTTP::UserAgent.new; $ua.auth( $username, $password ); my $response = $ua.get: $address; say $response.is-success ?? $response.content !! $response.status-line;</lang>

Phix

Library: libcurl

Exactly the same as the HTTP#Phix task. You can of course use curl_easy_setopt(curl,CURLOPT_USERPWD,"user:password") rather than embed that in the url. <lang Phix>include builtins\libcurl.e curl_global_init() atom curl = curl_easy_init() curl_easy_setopt(curl, CURLOPT_URL, "https://user:password@example.com/") object res = curl_easy_perform_ex(curl) curl_easy_cleanup(curl) curl_global_cleanup()

puts(1,res)</lang>

PicoLisp

<lang PicoLisp>(let (User "Bill" Pass "T0p5ecRet" Url "https://www.example.com")

  (in (list 'curl "-u" (pack User ': Pass) Url)
     (while (line)
        (doSomeProcessingWithLine @) ) ) )</lang>

Python

Works with: Python version 2.4 and 2.6

Note: You should install mechanize to run code below. Visit: http://wwwsearch.sourceforge.net/mechanize/

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

from mechanize import Browser

USER_AGENT = "Mozilla/5.0 (X11; U; Linux i686; tr-TR; rv:1.8.1.9) Gecko/20071102 Pardus/2007 Firefox/2.0.0.9"

br = Browser() br.addheaders = [("User-agent", USER_AGENT)]

  1. remove comment if you get debug output
  2. br.set_debug_redirects(True)
  3. br.set_debug_responses(True)
  4. br.set_debug_http(True)

br.open("https://www.facebook.com")

br.select_form("loginform") br['email'] = "xxxxxxx@xxxxx.com" br['pass'] = "xxxxxxxxx" br['persistent'] = ["1"]

response = br.submit() print response.read()</lang>

Library: Requests
Works with: Python version 2.7, 3.4–3.7

<lang python>import requests

username = "user" password = "pass" url = "https://www.example.com"

response = requests.get(url, auth=(username, password)

print(response.text)</lang>

Racket

<lang racket>

  1. lang racket

(require net/url net/url-connect openssl)

(module+ main

 (parameterize ([current-https-protocol (ssl-make-client-context)])
   (ssl-set-verify! (current-https-protocol) #t)
   ;; When this is #f, we correctly get an exception:
   ;; error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
   (when #t
     (ssl-load-verify-source! (current-https-protocol)
                              '(directory
                                ;; This location works on Debian 6;
                                ;; adjust as needed for your platform.
                                "/etc/ssl/certs"
                                )))
   (for ([l (in-port read-line (get-pure-port (string->url "https://www.google.com/")))])
     (displayln  l))))

</lang>

Ruby

<lang ruby>require 'uri' require 'net/http'

uri = URI.parse('https://www.example.com') response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|

 request = Net::HTTP::Get.new uri
 request.basic_auth('username', 'password')
 http.request request

end</lang>

Run BASIC

<lang runbasic>html "

LOGIN
UserName"
TEXTBOX #userName, "" 
html "
Password:"

PasswordBox #passWord, ""

html "
"

button #si, "Signin", [doSignin] html " " button #ex, "Exit", [exit]

html "
"

WAIT

[doSignin] loginUserName$ = trim$(#userName contents$()) loginPassWord$ = trim$(#passWord contents$()) if (loginUserName$ = "admin" and loginPassWord$ = "admin" then

  print "Login ok"
 else
  print "invalid User or Pass"
  cls
  goto [loop]

end if

print Platform$ ' OS where Run BASIC is being hosted print UserInfo$ ' Information about the user's web browser print UserAddress$ ' IP address of the user

[exit] end</lang>  

Scala

<lang Scala>import java.net.{Authenticator, PasswordAuthentication, URL}

import javax.net.ssl.HttpsURLConnection

import scala.io.BufferedSource


object Authenticated extends App {

 val con: HttpsURLConnection =
   new URL("https://somehost.com").openConnection().asInstanceOf[HttpsURLConnection]
 object PasswordAuthenticator extends Authenticator {
   override def getPasswordAuthentication = 
     new PasswordAuthentication("username", "password".toCharArray)
 }
 Authenticator.setDefault(PasswordAuthenticator)
 con.setAllowUserInteraction(true)
 con.connect()
 new BufferedSource(con.getInputStream).getLines.foreach(println(_))

}</lang>

Sidef

<lang ruby>require('WWW::Mechanize')

var mech = %s'WWW::Mechanize'.new(

   cookie_jar => Hash.new,
   agent => 'Mozilla/5.0',

)

mech.get('https://login.yahoo.com/') mech.submit_form(

   form_id => 'mbr-login-form',   # form id
   fields => Hash.new(
       'login'  => 'XXXXXX',
       'passwd' => 'YYYYYY',

))</lang>

Tcl

Works with: Tcl version 8.6
for the binary encode subcommand, otherwise uses
Library: Tcllib (Package: base64)

Uses the Tls package. <lang Tcl>package require http package require tls http::register https 443 ::tls::socket

  1. Generate the authentication

set user theUser set pass thePassword dict set auth Authenticate "Basic [binary encode base64 ${user}:${pass}]"

  1. Make a secure authenticated connection

set token [http::geturl https://secure.example.com/ -headers $auth]

  1. Now as for conventional use of the “http” package

set data [http::data $token] http::cleanup $token</lang>


Visual Basic

Works with: Visual Basic version 5
Works with: Visual Basic version 6
Works with: VBA version Access 97
Works with: VBA version 6.5
Works with: VBA version 7.1

<lang vb>Sub Main() ' in the "references" dialog of the IDE, check ' "Microsoft WinHTTP Services, version 5.1" (winhttp.dll) Dim HttpReq As WinHttp.WinHttpRequest Const WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 As Long = &H80& Const WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 As Long = &H200& Const WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 As Long = &H800& Const HTTPREQUEST_PROXYSETTING_PROXY As Long = 2

  1. Const USE_PROXY = 1
 Set HttpReq = New WinHttp.WinHttpRequest
 HttpReq.Open "GET", "https://www.abc.com/xyz/index.html"
 HttpReq.Option(WinHttpRequestOption_SecureProtocols) = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 Or _
                                                        WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 Or _
                                                        WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
 HttpReq.SetCredentials "<username>", "<password>", 0&
  1. If USE_PROXY Then
 HttpReq.SetProxy HTTPREQUEST_PROXYSETTING_PROXY, "10.167.1.1:80"
  1. End If
 HttpReq.SetTimeouts 1000, 1000, 1000, 1000
 HttpReq.Send
 Debug.Print HttpReq.ResponseText

End Sub</lang>

zkl

Using cURL to do the heavy lifting, get a XML list of computers connected to my router. <lang zkl>zkl: var ZC=Import("zklCurl") zkl: var data=ZC().get("http://usr:pw@192.168.1.1/computer_list.xml") L(Data(1,049),121,0) zkl: data[0][121,*].text</lang>

Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<computers>
<ip_address0>192.168.1.100</ip_address0><host_name0>core-shot
...