# Integration and Usage

{% hint style="info" %}
In this example we use [go-chi](https://github.com/go-chi/chi) to build the RESTful service. You can view the full code [here](https://github.com/ontology-tech/ontlogin-sample-go), and find the SDK [here](https://github.com/ontology-tech/ontlogin-sdk-go).
{% endhint %}

## Initialization <a href="#initialization" id="initialization"></a>

Add the following in the `go.mod` file.

```go
require (	...	github.com/ontology-tech/ontlogin-sdk-go latest)
```

## Add API Methods <a href="#add-api-methods" id="add-api-methods"></a>

Import the methods in the `main.go` file.

* `requestChallenge`: Returns the challenge from the server
* `submitChallenge` : Passes the signed challenge and VP (if requested by the server)

```go
package main​
import (	
        "log"
        "net/http"​
        "github.com/go-chi/chi/v5"	
        "github.com/go-chi/chi/v5/middleware"	
        "github.com/go-chi/cors"​	
        "ontlogin-sample/auth"	
        "ontlogin-sample/service"
)
```

&#x20;Initialize the service, perform cross-origin resource sharing checks and define API methods.

```go
func main() {
	r := chi.NewRouter()	
	service.InitService() // Service Initialization	
	r.Use(cors.Handler(cors.Options{		
		// AllowedOrigins:   []string{"https://foo.com"}, // Use this to allow specific origin hosts		
		AllowedOrigins: []string{"*"},		
		// AllowOriginFunc:  func(r *http.Request, origin string) bool { return true },		
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},		
		// AllowedHeaders:   []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},		
		AllowedHeaders:   []string{"Authorization", "Content-Length", "X-CSRF-Token", "Token", "session", "X_Requested_With", "Accept", "Origin", "Host", "Connection", "Accept-Encoding", "Accept-Language", "DNT", "X-CustomHeader", "Keep-Alive", "User-Agent", "X-Requested-With", "If-Modified-Since", "Cache-Control", "Content-Type", "Pragma"},		
		ExposedHeaders:   []string{"Content-Length", "token", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma", "FooBar"},		
		AllowCredentials: false,		
		MaxAge:           172800, // Maximum value not ignored by any of major browsers		
		//Debug:true,	
	}))	
	r.Use(middleware.Logger)	
	r.Use(auth.Middleware()) // Detect app login permission​	
	
	r.Post("/requestChallenge", service.RequestChallenge) // Challenge request	
	r.Post("/submitChallenge",service.Login) // Challenge submission	
	r.Get("/afterLogin",service.AfterLogin)  // Other business logic	
	log.Fatal(http.ListenAndServe(":3000", r))
}
```

## Import and Use `service.go` <a href="#import-and-use-service-go" id="import-and-use-service-go"></a>

Handle API requests using `service.go`

```go
package service​
import (
	"encoding/json"	
	"fmt"	
	"github.com/ontology-tech/ontlogin-sdk-go/did"	
	"github.com/ontology-tech/ontlogin-sdk-go/did/ont"	
	"github.com/ontology-tech/ontlogin-sdk-go/modules"	
	ontloginsdk "github.com/ontology-tech/ontlogin-sdk-go/sdk"	
	"net/http"​	
	
	"github.com/google/uuid"​	
	
	"ontlogin-sample/auth"	
	"ontlogin-sample/jwt"
)​

var loginsdk *ontloginsdk.OntLoginSdk
var mapstore map[string]string


​func InitService() {	
	mapstore = make(map[string]string) // To store UUID. In real projects, UUID can be stored in the database, redis or cache                                     	
	
	vcfilters := make(map[string][]*modules.VCFilter)		// Configure `VCFilter` according to `actionType`	
	vcfilters[modules.ACTION_REGISTER] = []*modules.VCFilter{		
		{Type: "EmailCredential", Required: true, TrustRoots: []string{"did:ont:ssssss"}}, // Issuer DID	
	}	// Server configuration information needed by the SDK, which can be obtained from config files	
	conf := &ontloginsdk.SDKConfig{		
		Chain: []string{"ont"}, // Supported chains, e.g. eth, ont, bsc, respective Processors needed		
		Alg:   []string{"ES256"}, // Supported signature schemes		
		ServerInfo: &modules.ServerInfo{			
			Name:               "testServcer",			
			Icon:               "http://somepic.jpg",			
			Url:                "https://ont.io",			
			Did:                "did:ont:sampletest",			
			VerificationMethod: "",		
		},		
		VCFilters: vcfilters,   // VC required by the server	
	}​	
	
	Processors := make(map[string]did.DidProcessor)  // Initialize the Processor of the respective chain
	// Parameter specification using Ontology as an example
	// 1. doubleDirection bool: if mutual authentication is required
	// 2. Ontology node rpc server address
	// 3. DID contract address, can be null when 1 takes `false`
	// 4. Ontology wallet address, can be null when 1 takes `false`
	// 5. Wallet password, can be null when 1 takes `false`		
	
	ontProcessor, err := ont.NewOntProcessor(false, "http://polaris2.ont.io:20336", "52df370680de17bc5d4262c446f102a0ee0d6312", "./wallet.dat", "123456")	
	if err != nil {
		panic(err)	
	}	
	Processors["ont"] = ontProcessor
	// Except config, Processor and SDK, the following functions need to be passed
	// 1. func()string: generates UUID
	// 2. func(string)error: checks if the nonce (UUID) exists in the database/redis/cache		
	loginsdk, err = ontloginsdk.NewOntLoginSdk(conf, Processors, GenUUID, CheckNonce)	
	if err != nil {		
		panic(err)	
	}
}

​func RequestChallenge(writer http.ResponseWriter, request *http.Request){  
	// Handle the request from the client	
	cr := &modules.ClientHello{}	
	writer.Header().Set("Content-Type", "application/json")	
	err := json.NewDecoder(request.Body).Decode(&cr)	
	if err != nil {		
		fmt.Printf("err:%s\n",err.Error())		
		writer.Write([]byte(err.Error()))		
		return	
	}  
	// Invoke the SDK to generate the challenge	
	serverHello,err := loginsdk.GenerateChallenge(cr)	
	if err!= nil{		
		fmt.Printf("err:%s\n",err.Error())		
		writer.Write([]byte(err.Error()))		
		return	
	}	  
	// Return the challenge	
	bts,_:=json.Marshal(serverHello)​	
	writer.Write(bts)
​}​

func Login(writer http.ResponseWriter, request *http.Request){
	lr := &modules.ClientResponse{}	
	writer.Header().Set("Content-Type", "application/json")​	
	
	err := json.NewDecoder(request.Body).Decode(&lr)​	
	
	if err != nil {
		fmt.Printf("err:%s\n",err.Error())		
		writer.Write([]byte(err.Error()))		
		return	
	}​	
	
	err = loginsdk.ValidateClientResponse(lr)	
	if err != nil {		
		fmt.Printf("err:%s\n",err.Error())		
		writer.Write([]byte(err.Error()))		
		return	
	}​
	// The challenge response from the client has passed validation
	// Now you can proceed according to your business logic
	// In this example, JWT is used for authentication​​	
	s ,err:= jwt.GenerateToken(lr.Did)​	
	writer.Write([]byte(s))
​}

​func AfterLogin(writer http.ResponseWriter, request *http.Request) {
	if err := auth.CheckLogin(request.Context()); err != nil {		
		fmt.Printf("err:%s\n", err.Error())		
		writer.Write([]byte("please login first"))		
		return	
	}	
	writer.Write([]byte("normal business process"))
}

​​func GenUUID()string{	
	uuid,err := uuid.NewUUID()	
	if err != nil{		
		fmt.Printf("uuid failed:%s\n",err.Error())		
		
		return ""	
	}	
	mapstore[uuid.String()] = "ok"	
	return uuid.String()
}​

func CheckNonce(nonce string)error{	
	if _,ok:=mapstore[nonce]
	;!ok{		
		return fmt.Errorf("no nonce found")	
	}	
	return nil
}
```

## Handle VP <a href="#handle-vp" id="handle-vp"></a>

Use the following to extract VC from VP in form of JSON text.

```go
 GetCredentialJson(chain, presentation string) ([]string, error)
```

Since the form of VC varies according to the server's request, only JSON is supported here. The server can parse the VC into the per-defined form.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ont.io/decentralized-identity-and-data/ontid/ont-login/back-end-go-sdk/integration-and-usage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
